/* BOI API v3.0 *********************************/
/* Project Name: Business Objects Integration	*/
/* Developed by: Ali H. Al-Towailib				*/
/*                                  			*/
/* **********************************************/
/* Change log:
 * v3.0.1: Merging the BOILib, BOIData,theme, boi_ui, currentDlg. under the BOI
 * v3.0: uses new BI Apps BackEnd
 * v2.0: uses old Dashboard Wizard BackEnd
 * v1.0: initial version using static xml
 */

/* Important: This API Requires initialization of jQuery first.
 /*
 * This API can be used by referencing BOI singleton instance. e.g. BOI.openDocument(...)
 * The instance itself must reside on the HTML Framework.
 * Singleton instance will be automatically initialised on script inclusion in any HTML document
 */

/**
 * ******************************* BOI Object Oriented Class Library
 * *******************************************
 */
var theme = 'theme';

var BOILib = {
    // Constants and Lookup enums
    VariableTypes:{
        Number:'number',
        String:'string',
        Date:'date',
        DateTime:'datetime',
        Time:'time',
        Boolean:'boolean'
    },
    F4Modes:{
        QueryDef:'QUERY_DEF',
        BWReport:'BW_REPORT'
    },

    SelectionTypes:{
        Single:'P',
        Multiple:'M',
        Range:'I',
        SelectionOption:'S'
    },

    OutputTypes:{
        XML:'xml',
        JSON:'json'
    },

    ReportTypes:{
        Bex3:'bex3',
        WAD3:'Wad3',
        WAD7:'Wad7',
        Bex7:'bex7',
        Webi:'webi',
        Xcelsius:'xcelsius',
        XcelsiusLocal:'xcelsiuslocal',
        Crystal:'crystal',
        Explorer:'explorer',
        Analysis:'analysis',
        URL:'url',
        BO:'BO',
        DesignStudio:'desingstudio',
        Flash:'flash',
        ReportGroup:'REPORT_GROUP',
        KPI:"KPI"
    },

    ReportStates:{
        Current:"current", // report has current variable values
        RefreshNeeded:"refresh", // report has obsolete variable values and
        // needs to be reopened
        Executed:"executed"
    },

    Report:function Report() {
        this.app_id = undefined;
        this.role = "REPORTROLE";
        this.id = "report id";
        this.url = "http://myreporturl.com/"; // Report URL
        this.tech_name = "My Report TECHNAME";
        this.label = "My Report Label";
        this.description = "REPORT DESCRIPTION";

        this.state = BOILib.ReportStates.RefreshNeeded;
        this.type = "BO"; // Report Type
        // (bex3,bex7,webi,crystal,xcelsius,explorer,analysis)
        this.layout = null; // report display layout info
        this.varlayout = null; // report variables layout info
        this.vars = ""; // string representing variables
        this.variables = {}; // Assigned Variable objects
        this.metadata = null;
        this.reports = {};
        this.parent_id = undefined;

        this.kpi = {};// kpi definition for charting etc.
        this.replayout = null; // layout definition for report group

        this.VARIABLE_SCREEN = false; // force variable screen before
        // execution
        this.KPI_DRL_DOWN_URL = ""; // drill down url for kpis
        this.content_loaded = false;

        this.getInfo = function () {
            var output = '';
            var varcount = 0;

            for (var i in this.variables) {
                varcount++;
                output += '\n\t\t' + this.variables[i].getInfo();
            }

            return '\n\t----- BEGIN CURRENT REPORT INFORMATION -----------------------------------------'
                + '\n\tReport Id: '
                + this.id
                + '\n\tReport Tech Name: '
                + this.tech_name
                + '\n\tReport URL: '
                + this.url
                + '\n\tVariables Count: '
                + varcount
                + '\n\tVariables Stored:'
                + output
                + '\n\tVariables Original String: '
                + this.vars
                + '\n\t----- END OF CURRENT REPORT INFORMATION -----------------------------------------';
        };
    },

    Range:function Range(fromMode, from, to, toMode, operator) {
        this.operator = operator ? operator : "bt";// possible operators using
        // abap like syntax :
        // bt,gt,ge,lt,le,eq
        this.fromMode = fromMode ? fromMode : "["; // default to inclusion
        // using BO OpenDoc Syntax
        this.toMode = toMode ? toMode : "]"; // default to inclusion, use (
        // for excluding value
        this.from = from ? from : "";
        this.to = to ? to : "";
    },

    Variable:function Variable() {
        this.name = ""; // ZVARNAME
        this.description = ""; // ZVAR_DESCRIPTION
        this.type = BOILib.VariableTypes.Number; // date,datetime,time,boolean,number,string
        this.seltype = BOILib.SelectionTypes.Single; // variable selection
        // type
        this.f4type = BOILib.F4Modes.QueryDef; // or BW_REPORT
        this.f4query = ""; // query to execute in order to get F4 values
        this.defval = ""; // DEF_VAL
        this.value = undefined; // current value, can be date object
        this.values = []; // for multi value variable (if type is date,
        // contains date objects)
        this.ranges = []; // for single or multi range variable (contains
        // Range objects)
        this.dependencies = {}; // what vars this variable depends on

        this.display = ""; // VIEW_ID: CHECK_BOX, etc
        this.group = 0;
        this.location = 0;
        this.URL_PARAM = "";

        this.isReady = function () // determines if this variable is ready for
            // use (i.e. dependencies must have values)
        {
            for (var i in this.dependencies)
                if (this.dependencies[i].value == undefined)
                    return false;
            return true;
        };

        this.getInfo = function () {

            var f4count = 0;
            for (property in this.F4)
                f4count++;

            var vals = '';
            if (this.seltype == BOILib.SelectionTypes.Multiple)
                for (var i in this.values)
                    vals += this.values[i] + "|";

            return this.name + ' (' + this.description + '), Value:'
                + this.value + ', F4:' + f4count + ', MultiValues:' + vals;
        };
    },

    F4:function F4() {
        this.name = "My F4 Entry"; // F4 Entry Name
        this.value = "1"; // F4 Entry Value

        this.getInfo = function () {
            return this.name + ':' + this.value;
        };
    },

    F4Set:function F4Set() {
        this.varname = "My Variable"; // F4Set Entry Name
        this.values = {}; // F4 Objects
        this.json = "{[]}";
        this.cycle = 1; // start index
        this.records = 100; // page size
        this.total = 200; // total records available
        this.url = "";

        this.getInfo = function () {
            return this.name + ':' + this.value;
        };
    },

    Uri:function Uri(fullurl) {
        this.url = ""; // url without query string
        this.fullUrl = ""; // Complete url
        this.params = {}; // param['var1']=4545, param['var2']=34554, etc..
        // key value pairs

        if (fullurl) {
            this.url = fullurl.split('?')[0];
            this.fullUrl = fullurl;
            if (fullurl.indexOf('?') > -1) {
                var querystring = fullurl.split('?')[1];
                if (querystring.indexOf('&') > -1) {
                    var parameters = querystring.split('&');
                    for (var i in parameters) {
                        if (parameters[i].indexOf('=') > -1) {
                            var block = parameters[i].split('=');
                            this.params[block[0]] = block[1];
                        }
                    }
                } else {
                    var block = querystring.split('=');
                    this.params[block[0]] = block[1];
                }
            }
        }

        this.post = function (target) {
            if (this.url == "")
                return;

            target = typeof target !== 'undefined' ? target : '_blank'; // use
            // defaults
            // if
            // not
            // specified

            // create an iframe
            // create a form
            // put the params in hiddenfields
            // post the form to the target

            var form = BOI.doc.createElement("form");
            form.setAttribute("method", 'post');
            form.setAttribute("action", this.fullUrl);
            form.setAttribute("target", target);

            for (var key in this.params) {
                if (this.params.hasOwnProperty(key)) {
                    var hiddenField = BOI.doc.createElement("input");
                    hiddenField.setAttribute("type", "hidden");
                    hiddenField.setAttribute("name", key);
                    hiddenField.setAttribute("value", this.params[key]);
                    form.appendChild(hiddenField);
                }
            }

            BOI.doc.body.appendChild(form);
            form.submit();

            BOI.doc.body.removeChild(form);

            return this.fullUrl;
        };

        this.get = function (target) {
            target = typeof target !== 'undefined' ? target : '_blank'; // use
            // defaults
            // if
            // not
            // specified

            // create an iframe
            // create a form
            // put the params in hiddenfields
            // post the form to the target

            var form = document.createElement("form");
            form.setAttribute("method", 'get');
            form.setAttribute("action", this.url);
            form.setAttribute("target", target);

            for (var key in this.params) {
                if (this.params.hasOwnProperty(key)) {
                    var hiddenField = document.createElement("input");
                    hiddenField.setAttribute("type", "hidden");
                    hiddenField.setAttribute("name", key);
                    hiddenField.setAttribute("value", this.params[key]);
                    form.appendChild(hiddenField);
                }
            }

            document.body.appendChild(form);
            form.submit();

            document.body.removeChild(form);

            return this.fullUrl;
        };

        this.ajaxPost = function (successFunction) {
            var params = {};
            // decode any stuff
            for (var key in this.params)
                params[key] = decodeURIComponent(this.params[key]);

            $.ajax({
                url:this.url,
                data:params,
                type:'POST',
                dataType:'text',
                success:function (data) {
                    if (successFunction)
                        successFunction(data);
                }
            });
        }
    },

    Context:function Context() {
        this.parent = BOI;
        this.lastReport = new BOILib.Report(); // last opened report
        this.lastUrl = "";
        this.reports = {}; // array of reports from catalog
        this.vars = ""; // string representing last variables passed
        this.variables = {}; // Array of Current Variable objects
        this.reportCatalog = null; // xml
        this.reportCatalogJSON = null; // json
        this.reportCatalogTree = null; // json tree with isFolder attributes

        this.populateCatalog = function (reload) // creates initial report
            // objects
        {
            var count = 0;
            var context = this;

            if (reload == true) {
                context.reports = {};
            }
            // '*[tech_name][isBranch="false"],*[type="REPORT_GROUP"]'
            // Ansaj ,16-jan-14 : Modified condition for backward compatibility
            // Saleh ,20-Jan-14 : // Modified condition for check the condition
            // for backcompatibility

            var data;
            if (this.reportCatalog.xml) {
                data = BOILib.parseXml(this.reportCatalog);
            }
            else {
                data = this.reportCatalog;
            }
            $(data).find('node[isBranch="false"],node[type="REPORT_GROUP"]')
                .each(function () {
                    rep_id = $(this).attr("id");

                    // if the report is there in context, take it.
                    if ((!context.reports[rep_id]) || (reload == true)) {

                        var report = new BOILib.Report();
                        report.role = $(this).attr("role");
                        report.id = $(this).attr("id");
                        report.url = $(this).attr("url");
                        report.tech_name = $(this).attr("tech_name");
                        report.type = $(this).attr("type");
                        report.label = $(this).attr("title");
                        report.parent_id = $(this).parent().attr("id");
                        report.VARIABLE_SCREEN = $(this).attr("variable_screen");
                        //31-Mar-2014 Ansaj , Added for showing defaul varibale screen
                        report.repdefinition = $(this).attr("rep_definition");
                        var openStyle = $(this).attr("OPEN_STYLE");

                        if (openStyle) {
                            report.OPEN_STYLE = openStyle;
                        }
                        context.reports[report.id] = report;
                    }
                    count++;
                });

            // Report Groups
            for (var i in context.reports) {
                var report = context.reports[i];
                if (report.type == BOILib.ReportTypes.ReportGroup) {
                    report.tech_name = report.id;
                    for (var j in context.reports) {
                        var context_report = context.reports[j];
                        if (context_report.parent_id == report.id)
                            report.reports[context_report.id] = context_report;
                    }
                }
            }

            BOI.Events.raiseEvent(BOI.Events.contextchange, []);

            if (parent.debugMode)
                BOI.log += BOILib.Util.log('Done Populating Context with '
                    + count + ' reports');
        };
        this.getInfo = function () {
            var output = '';
            var varcount = 0;

            for (var i in this.variables) {
                varcount++;
                output += '\n\t' + this.variables[i].getInfo();
            }

            return '\n----- BEGIN CONTEXT INFORMATION -----------------------------------------'
                + '\nLast Report id: '
                + this.lastReport.id
                + '\nLast Report TechName: '
                + this.lastReport.tech_name
                + '\nLast Generated Report URL: '
                + this.lastUrl
                + '\nContext Variables Count: '
                + varcount
                + '\nListing of Variables Stored:'
                + output
                + '\nVariables Original String(if provided): '
                + this.vars
                + '\nLast Report Info: '
                + this.lastReport.getInfo()
                + '\n----- END OF CONTEXT INFORMATION -----------------------------------------';
        };

        this.generateReportUri = function (report, reportVarsOnly, reportViewType) // returns a URI object
        {
            var url = '';
            var id = report.id;
            var type = report.type;

            switch (report.type) // check the type
            {
                case BOILib.ReportTypes.KPI:
                    url = report.url;
                    break;
                case BOILib.ReportTypes.URL:
                case "URL":
                    url = report.url;
                    break;
                case BOILib.ReportTypes.Bex3:
                case "BW_BEX3":
                    url = this.generateBex3URL(id, type, reportVarsOnly);
                    url = BOI.urlForBex3 + url;
                    //28-jan-2014 Ansaj , Added for query template.
                    if (report.QUERY_TEMPLATE) {
                        url += "&template_id=" + report.QUERY_TEMPLATE + "";
                    }
                    // 3-Mar-2014 Ansaj , added for showing the default variable screen for bex7
                    if (report.repdefinition == "VARIABLE_SCREEN") {
                        url += "&VARIABLE_SCREEN=X";
                    }
                    break;
                case BOILib.ReportTypes.WAD3:
                case "BW_WAD3":
                    url = this.generateBex3URL(id, type, reportVarsOnly);
                    url = BOI.urlForWAD3 + url;
                    break;
                case BOILib.ReportTypes.WAD7:
                case "BW_WAD7":
                    url = this.generateBex7URL(id, type, reportVarsOnly);
                    url = BOI.urlForWAD7 + url;
                    break;
                case BOILib.ReportTypes.Bex7:
                case "BW_BEX7":
                    url = this.generateBex7URL(id, type, reportVarsOnly);
                    url = BOI.urlForBex7 + url;
                    //28-jan-2014 Ansaj , Added for query template.
                    if (report.QUERY_TEMPLATE) {
                        url += "&template=" + report.QUERY_TEMPLATE + "";
                    }
                    // 3-Mar-2014 Ansaj , added for showing the default variable screen for bex7
                    if (report.repdefinition == "VARIABLE_SCREEN") {
                        url += "&VARIABLE_SCREEN=X";
                    }
                    break;
                case BOILib.ReportTypes.BO:
                case BOILib.ReportTypes.Webi:
                case BOILib.ReportTypes.Crystal:
                case BOILib.ReportTypes.DesignStudio:
                case "BO_WEBI":
                case "BO_CRYSTAL":
                    url = this.generateOpenDocumentURL(id, type, reportVarsOnly);

                    // handle refresh
                    if (this.reports[id].state == BOILib.ReportStates.RefreshNeeded)
                        url = "&sRefresh=Y" + url;
                    else
                        url = "&sRefresh=N" + url;
                    url = BOI.urlForOpenDocument + report.tech_name + url;
                    url = BOI.protocolForBOServer + BOI.urlForServer + "/" + url;
                    if (reportViewType == undefined) {
                        reportViewType = 'html';
                        url = url + '&sViewer=html'
                    }
                    break;
                case "BO_DASHBOARD":
                case BOILib.ReportTypes.Xcelsius:
                    url = this.generateXcelsiusURL(id, type, reportVarsOnly);
                    url = url.replace('?', '&');
                    url = BOI.urlForOpenDocument + report.id + url;
                    url = BOI.protocolForBOServer + BOI.urlForServer + "/" + url;
                    break;
                case "BW_DASHBOARD":
                case BOILib.ReportTypes.XcelsiusLocal:
                case BOILib.ReportTypes.Flash:
                    url = this.generateXcelsiusURL(id, type, reportVarsOnly);
                    break;
                case "BO_EXPLORER":
                case "BO_ANALYSIS":
                case BOILib.ReportTypes.Explorer:
                case BOILib.ReportTypes.Analysis:
                    url = this.generateOpenDocumentURL(id, type, reportVarsOnly);
                    url = BOI.urlForOpenDocument + report.id + url;
                    break;
            }

            var Uri = new BOILib.Uri(url);
            this.lastUrl = Uri.fullUrl;
            return Uri; // returns a URI object
        };

        this.getReportVariables = function (id, reportVarsOnly) {
            var variables = [];
            if (reportVarsOnly) {
                for (var i in this.reports[id].variables) {
                    var varname = this.reports[id].variables[i].name;
                    //
                    if (BOI.single_variable_screen) {
                        // if we want to take the single variable, then take it
                        // from the BOI context
                        variables.push(this.variables[varname]);
                    } else {
                        // If the report need to be executed with variables
                        // specific to the report, then
                        // get the report variables
                        variables.push(this.reports[id].variables[varname]);
                    }

                }
            } else {
                for (var i in this.variables) {
                    variables.push(this.variables[i]);
                }
            }
            return variables;
        };

        this.generateBex3URL = function (id, type, reportVarsOnly) {

            var variables;
            variables = this.getReportVariables(id, reportVarsOnly);

            // now we have all the variables
            // begin bex3 logic here...
            var url = BOILib.BexSyntax.getBex3URL(this.reports[id].tech_name,
                variables);
            return url;

        };
        this.generateBex7URL = function (id, type, reportVarsOnly) {
            var variables;
            variables = this.getReportVariables(id, reportVarsOnly);

            // now we have all the variables
            // begin bex3 logic here...
            var url = BOILib.BexSyntax.getBex7URL(this.reports[id].tech_name,
                variables);
            return url;
        };
        this.generateOpenDocumentURL = function (id, type, reportVarsOnly) {
            var variables;
            variables = this.getReportVariables(id, reportVarsOnly);

            var output = "";

            // now we have all the variables
            // begin openDocument logic here...

            if (variables.length > 0) {
                for (var i in variables) {
                    output += BOILib.OpenDocumentSyntax.getVariableValue(
                        variables[i], type);
                }
            }
            return output;
        };
        this.generateXcelsiusURL = function (id, type, reportVarsOnly) {
            var variables;
            variables = this.getReportVariables(id, reportVarsOnly);

            var output = "";
            // now we have all the variables
            // begin url syntax logic here: file.swf?varname=value&var2=val2&...

            if (variables.length > 0) {
                var isLocal = type == BOILib.ReportTypes.XcelsiusLocal
                    || BOILib.ReportTypes.Flash;
                for (var i in variables) {
                    var val = variables[i].value;
                    if (variables[i].type == BOILib.VariableTypes.Date) {
                        var m = val.getMonth() + 1;
                        var d = val.getDate();
                        var y = val.getFullYear();

                        if (m < 10)
                            m = "0" + m;
                        if (d < 10)
                            d = "0" + d;
                        val = m + '' + d + '' + y;
                    }

                    if (isLocal)
                        output += '&' + variables[i].name + '=' + val;
                    else
                        output += '&lsS' + variables[i].name + '=' + val;
                }
            }
            if (isLocal)
                return output.substr(1);
            else
                return output;
        };
    },

    parseXml:function parseXml(xml) {
        if (navigator.appName == 'Microsoft Internet Explorer') {
            var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.loadXML(xml.xml);
            xml = xmlDoc;
        }
        return xml;
    },
    Property:function Property(comp_id, name) {
        this.panel_id = undefined;
        this.comp_id = comp_id;
        this.name = name;
        this.description = "";
        this.value = ""; // can be simple string or array (for multiple
        // values)
        this.display = "TEXTBOX"; // can be textbox, dropdown, checkbox, radio
        this.mode = "S"; // s=single, m=multiple values
        this.options = []; // array of possible values (used for dropdown/radio
        // displays)
        this.getAssignmentRecord = function () {
            var valueString = '';
            if (this.value instanceof Array) {
                for (var i in this.value)
                    if (this.value[i])
                        valueString += '|' + this.value[i];
                if (valueString.indexOf('|') > -1)
                    valueString = valueString.substr(1);
            } else
                valueString = this.value;

            var record = BOIData.data.createRecord({
                APP_ID:[ BOI.app_id ],
                PANEL_ID:[ this.panel_id ],
                COMP_ID:[ this.comp_id ],
                PROP:[ this.name ],
                VALUE:[ valueString ]
            });
            return record;
        }
    },

    Component:function Component(comp_id) {
        // this.prototype = null;
        this.app_id = "";
        this.comp_id = comp_id;
        this.panel_id = "";
        this.title = "";
        this.description = "";
        this.url = ""; // location of component html
        this.order = 0;
        this.properties = {}; // hashset of property objects with all their
        // definitions
        this.element = null; // the iframe element in parent
        this.iframe = null; // the iframe document with usable
        // functions/variables
        this.setProperties = function () {
            // locate the iframe object of this component and set its properties
            if (this.iframe) {
                var propertyvalues = {}; // simple hashset of key/value pairs
                // to send to the iframe element
                // TODO: build propertyvalues from this.properties object
                for (var p in this.properties) {
                    var prop = this.properties[p];
                    propertyvalues[prop.name] = prop.value;
                }
                if (this.properties.height)
                    $(this.element)
                        .attr("height", this.properties.height.value);
                this.iframe.properties = propertyvalues; // direct access to
                // iframe component
                // properties
                // attribute
                this.iframe.refreshProperties(); // notifies the iframe
                // component of property
                // change
            }
        };
        this.setProperty = function (name, value) {
            // set an individual property value
            this.properties[name].value = value; // update the object
            if (this.iframe) {
                this.iframe.properties[name] = value; // direct access to
                // iframe component
                // properties attribute
                this.iframe.refreshProperties(); // notifies the iframe
                // component of property
                // change
            }
        }
        this.initialize = function () {
            // execute the initialize function of this component's iframe code
            // TODO proper executing of frame functions
            if (this.element) {
                $(this.element).attr("name",
                    'COMP_' + this.panel_id + '_' + this.comp_id);
                this.iframe = window.frames[$(this.element).attr("name")];
                this.iframe = this.element.contentWindow;
                if (this.iframe)
                    if (this.iframe.document.readyState == "complete") {
                        this.setProperties();
                        this.iframe.initialize();
                    }
            }
        };
        this.getAssignmentRecord = function () {
            var record = BOIData.data.createRecord({
                APP_ID:[ BOI.app_id ],
                PANEL_ID:[ this.panel_id ],
                COMP_ID:[ this.comp_id ],
                DISPLAY_ORDER:[ this.order ]
            });
            return record;
        }
    },

    Panel:function Panel(layout_element_id, panel_id) {
        this.layout_id = layout_element_id;
        this.panel_id = panel_id; // top,left,center,right,bottom
        this.properties = {
            width:{
                name:"width",
                value:"100%",
                display:"TEXTBOX"
            },
            height:{
                name:"height",
                value:"100%",
                display:"TEXTBOX"
            },
            collapsible:{
                name:"collapsible",
                value:"",
                display:"CHECKBOX"
            },
            resizable:{
                name:"resizable",
                value:"",
                display:"CHECKBOX"
            },
            disabled:{
                name:"disabled",
                value:"",
                display:"CHECKBOX"
            }
        }
        this.element = $('#' + panel_id).get(0); // the actual html element
        // representing this panel
        this.components = {}; // hashset of components

        this.setProperties = function () {
            // set styling properties for this panel
            $(this.element).width(this.properties.width.value);
            $(this.element).height(this.properties.height.value);
            if (this.properties.disabled == "X")
                $(this.element).hide();
        }

        this.assignComponent = function (comp_id, order) {
            if (this.element) {
                // register a copy of the available component
                // Deep copy clone
                this.components[comp_id] = jQuery.extend(true, {},
                    BOI.Designer.Components[comp_id]);
                var component = this.components[comp_id];

                // deep copy properties
                for (var p in component.properties) {
                    component.properties[p] = jQuery.extend(true, {},
                        BOI.Designer.Components

                            [comp_id].properties[p]);
                    component.properties[p].panel_id = this.panel_id;
                }

                component.panel_id = this.panel_id;
                // create the component element
                /*
                 * if(component.element == null) { component.element = $("<iframe
                 * src='" + component.url + "'></iframe>").get(0); }
                 */

                // insert the component element into the panel
                var comp_name = 'COMP_' + this.panel_id + '_'
                    + component.comp_id;
                component.element = $(
                    "<iframe frameborder='0' scrolling='no' allowTransparency='true' name='" + comp_name + "' id='" + comp_name
                        + "' src='" + component.url + "'></iframe>")
                    .get(0);
                // component.element = $(component.element.outerHTML).get(0);
                // $(component.element).attr('name',
                // 'COMP_' + this.panel_id + '_' + component.comp_id);
                $(this.element).append(component.element);

                $(component.element).load(function () {
                    component.initialize();
                });

                // TODO: logic for location order
                component.order = $(component.element).index();

                return component;
            }
        }
        this.unassignComponent = function (comp_id) {

            // remove from the panel element
            $(this.components[comp_id].element).remove();

            // remove reference
            delete this.components[comp_id];

        }
        this.getAssignmentRecord = function () {
            var record = BOIData.data.createRecord({
                APP_ID:[ BOI.app_id ],
                PANEL_ID:[ this.panel_id ],
                WIDTH:[ this.properties.width.value ],
                HEIGHT:[ this.properties.height.value ],
                DISABLE:[ this.properties.disabled.value ],
                COLLAPSE:[ this.properties.collapsible.value ],
                RESIZE:[ this.properties.resizable.value ]
            });

            return record;
        }
    },

    OpenDocumentSyntax:{
        getVariableValue:function (variable, reporttype) // single,multiple,range
        {
            var type = reporttype;// syntax is different based on type: webi,
            // crystal, etc
            switch (variable.seltype) {
                case BOILib.SelectionTypes.Single:
                    return this.getSingleSyntax(variable, type);
                    break;
                case BOILib.SelectionTypes.Multiple:
                    return this.getMultipleSyntax(variable, type);
                    break;
                case BOILib.SelectionTypes.Range:
                    // add for temporary the ranges
                    if (variable.ranges[0] != undefined) {
                        return this.getRangeSyntax(variable, type);
                    } else {
                        BOILib.Util.log('The variable "' + variable.description
                            + '" is not configured with proper type. (Type='
                            + variable.seltype + ')', false);

                    }
                    break;
                default:
                    return '';
                    break;
            }
        },

        getValueFormat:function (variable, valueEntry) // formats the supplied
            // single value
            // according to
            // variabletype
        {
            // returns ? (WEBI only: forces prompt to user to enter value)
            // returns Paris (text)
            // returns 2004 (number)
            // returns Date(2004,1,24) (date)
            // returns DateTime(2004,1,24,6,1,1) (datetime)
            // returns Time(6,10,1) (time)
            // returns false (boolean)

            switch (variable.type) {
                // check type
                case BOILib.VariableTypes.Number:
                case BOILib.VariableTypes.String:
                    return valueEntry;
                    break;
                case BOILib.VariableTypes.Date: // supplied value must be of type
                    // Date()
                    return 'Date(' + valueEntry.getFullYear() + ','
                        + (valueEntry.getMonth() + 1) + ','
                        + valueEntry.getDate() + ')';
                    break;
                case BOILib.VariableTypes.DateTime:
                case BOILib.VariableTypes.Time:
                    return 'DateTime(' + valueEntry.getFullYear() + ','
                        + (valueEntry.getMonth() + 1) + ','
                        + (valueEntry.getDate()) + ','
                        + (valueEntry.getHours()) + ','
                        + (valueEntry.getMinutes()) + ','
                        + valueEntry.getSeconds() + ')';

                    break;
                case BOILib.VariableTypes.Boolean: // X=TRUE, blank = false
                    return valueEntry;
                    break;
            }
        },

        getMultipleSyntax:function (variable, type) {
            // returns lsM[Select+Cities]=[Paris],[London],[etc...] for Crystal
            // returns lsMSelect+Cities=Paris;London;etc... for Webi
            // the multiple values can have formats like
            // date,datetime,time,boolean,number,etc..
            // similar to the formats in examples below
            var output = '';
            var encStart = "[";
            var encEnd = "]";
            var separator = ","; // comma for crystal, for webi use ;

            if (type != BOILib.ReportTypes.Crystal) {
                encStart = "";
                encEnd = "";
                separator = ";";
            }

            for (var i in variable.values) {
                output += encStart
                    + this.getValueFormat(variable, variable.values[i])
                    + encEnd + separator;
            }
            if (output.indexOf(separator) > -1)
                output = output.substr(0, output.length - 1); // remove last
            // extra
            // separator
            if (output == undefined || output == "") {
                output = '';
            }
            return '&lsM' + variable.URL_PARAM + '=' + output;
        },

        getRangeSyntax:function (variable, type) {
            // returns lsRTime+Period=[a..d] (set text range)
            // returns lsRTime+Period=[2004..) (set number range start only)
            // returns lsRTime+Period=(..2004] (set number range end only)
            // returns lsRTime+Period=[2004..2009] (set number range)
            // returns lsRTime+Period=[Date(2004,1,24)..Date(2009,2,23)] (set
            // date range)
            // returns
            // lsRTime+Period=[DateTime(2004,1,24,7,1,1)..DateTime(2009,2,23,12,1,1)]
            // (set datetime range)
            // returns lsRTime+Period=[Time(7,1,1)..Time(12,1,1)] (set time
            // range)

            var encStart = "[";
            var encEnd = "]";
            var separator = ","; // comma for crystal, for webi use ;
            var fromMode = variable.ranges[0].fromMode;
            var toMode = variable.ranges[0].toMode;

            if (type != BOILib.ReportTypes.Crystal) {
                encStart = "";
                encEnd = "";
                separator = ";";
                fromMode = "";
                toMode = "";
            }
            var varfrom = this
                .getValueFormat(variable, variable.ranges[0].from);
            if (varfrom == undefined) {
                varfrom = '';
            }
            var varto = this.getValueFormat(variable, variable.ranges[0].to);
            if (varto == undefined) {
                varto = '';
            }
            return '&lsR' + variable.URL_PARAM + '=' + fromMode + varfrom
                + '..' + varto + toMode;

        },

        getSingleSyntax:function (variable, type) {
            // returns lsSSelect+City=? (WEBI only: forces prompt to user to
            // enter value)
            // returns lsSSelect+City=Paris (text)
            // returns lsSSelect+Year=2004 (number)
            // returns lsSSelect+Date=Date(2004,1,24) (date)
            // returns lsSSelect+Date=DateTime(2004,1,24,6,1,1) (datetime)
            // returns lsSSelect+Date=Time(6,10,1) (time)
            // returns lsSBoolean+Choice=false (boolean)

            var encStart = "[";
            var encEnd = "]";
            var separator = ","; // comma for crystal, for webi use ;

            if (type != BOILib.ReportTypes.Crystal) {
                encStart = "";
                encEnd = "";
                separator = ";";
            }
            var varval = this.getValueFormat(variable, variable.value);
            if (varval == undefined)
                varval = '';
            return '&lsS' + variable.URL_PARAM + '=' + varval;
        }
    },

    BexSyntax:{
        getBex3URL_XML:function (query_name, variables, baseurl) {
            try {
                var var_details = "";
                var cnt = 0;

                var_details = this.getBEX3Variables(variables);

                var partURL = query_name;// '/sap/bw/BEx?=&VARIABLE_SCREEN=&QUERY='+
                // query_name + '&var....' ;
                partURL = partURL + "&variables="
                    + encodeURIComponent(var_details);
                if (baseurl == undefined) {
                    baseurl = BOILib.Util.getBaseUrlBWAbap() + "zbw_reporting/execute_report_oo.htm";
                }
                var url = baseurl + "?query=" + partURL;
                return url;

            } catch (e) {
                BOI
                    .displayLog('Error while executing report (getBex3URL_XML) : '
                        + query_name + ", " + e);

            }
        },
        getBEX3Variables:function (variables) {
            var url = "";
            var cnt = 0;
            for (var i in variables) {
                //added by ALHASASA for vars not selected in var screen om 9-FEB-2014
                if (variables[i].value.length > 0 || variables[i].value.toString().length > 0) {
                    var name = variables[i].name;
                    var value = variables[i].value;
                    var values = variables[i].values;
                    var ranges = variables[i].ranges;
                    var type = variables[i].type; // date,datetime,time,boolean,number,string
                    var selectionType = variables[i].seltype; // S=Single,M=Multiple,R=Range
                    var VARTYP = variables[i].VARTYP;

                    var date_str = "", range_str = {
                        "from":"",
                        "to":"",
                        "operator":""
                    };

                    if (selectionType == BOILib.SelectionTypes.Single) {
                        cnt++;
                        // = value //in case not date
                        // For Date:check js date object reference for methods and
                        // return types..
                        if (type == 'date')
                            value = this.dateToString(value);

                        url += this.Bex3VarFormat(name, cnt)
                            + this.Bex3ValFormat(value, cnt);
                        if (VARTYP == 2) {
                            url += this.getHierarchyFormat(variables[i], cnt);
                        }

                    }

                    if (selectionType == BOILib.SelectionTypes.Multiple) {
                        if (values.length > 0)
                            cnt++;
                        for (var x in values) {
                            cnt += parseInt(x);
                            var myvalue = values[x];

                            if (type == 'date')
                                myvalue = this.dateToString(myvalue);

                            url += this.Bex3VarFormat(name, cnt)
                                + this.Bex3ValFormat(myvalue, cnt);
                            if (VARTYP == 2) {
                                url += this.getHierarchyFormat(variables[i], cnt);
                            }
                            // in case of data type is date
                            // For Date:check js date object reference for methods
                            // and return types..
                            // myvalue.getDate() //returns day
                        }
                    }

                    if (selectionType == BOILib.SelectionTypes.Range) {
                        if (typeof ranges == "object") {
                            if (ranges.length > 0)
                                cnt++;
                            for (var r in ranges) {
                                var myrange = ranges[r];
                                if (type == 'date') {

                                    range_str.from = this
                                        .dateToString(myrange.from);
                                    range_str.to = this.dateToString(myrange.to);
                                    range_str.operator = myrange.operator;
                                    myrange = range_str;

                                }
                                // myrange.operator
                                // myrange.from
                                // myrange.to...
                                // For Date:check js date object reference for
                                // methods and return types..

                                cnt += parseInt(r);

                                url += this.Bex3VarFormat(name, cnt)
                                    + this.Bex3RangeValFormat(myrange, cnt);

                            }
                        }

                    }
                }
            }
            return url;
        },
        getHierarchyFormat:function (variable, cnt) {
            // this is hierarchy node value. This will work only in
            // 0ORGUNIT case where all hierarchy nodes and leaves are
            // infoobject values
            // return url += '&var_node_iobjnm_'+cnt +'=' + variable.IOBJNM;
            var orgurl = '&var_node_iobjnm_' + cnt + '=' + variable.IOBJNM;
            return orgurl;

            // TODO:: This logic need to be enhanced for complex hierarchy
            // such as COSTCENTER where you have 0HIER_NODE and
            // InfoObject combined.
        },
        getBex3URL:function (query_name, variables) // tech_name = report or
            // query name, variables
            // is an optional array
            // of Variable objects
        {
            try {
                var url = "";

                url = this.getBEX3Variables(variables);

                var fullURL = query_name;// '/sap/bw/BEx?=&VARIABLE_SCREEN=&QUERY='+
                // query_name + '&var....' ;
                return fullURL + url;// + encodeURIComponent(url);
            } catch (e) {
                BOI.displayLog('Error while executing report (BEX3) : '
                    + query_name + ", " + e);

            }
        },

        Bex3VarFormat:function (varName, n) {
            return '&var_name_' + n + '=' + varName;
        },

        Bex3ValFormat:function (varValue, n) {
            return '&var_value_ext_' + n + '=' + varValue + '&var_operator_'
                + n + '=EQ' + '&var_value_low_ext_' + n + '=' + varValue;
        },

        Bex3RangeValFormat:function (range, n) {
            return '&var_operator_' + n + '=' + range.operator
                + '&var_value_low_ext_' + n + '=' + range.from
                + '&var_value_high_ext_' + n + '=' + range.to
                + '&var_value_ext_' + n + '=' + range.from;

        },

        /*
         * convert a date obj to string MMDDYYYY
         */
        dateToString:function (date) {
            if (date.getUTCMonth && date.getDate && date.getFullYear) {
                var month = date.getUTCMonth() > 8 ? date.getUTCMonth() + 1
                    : '0' + date.getUTCMonth() + 1;
                var day = date.getDate() > 9 ? date.getDate() : '0'
                    + date.getDate();
                var year = date.getFullYear();

                return month + day + year;
            }

        },

        /* BEX7 */

        getBex7URL:function (tech_name, variables) {

            var url = tech_name;
            var cnt = 0;
            for (var i in variables) {
                var name = variables[i].name;
                var value = variables[i].value;
                var values = variables[i].values;
                var ranges = variables[i].ranges;
                var type = variables[i].type; // date,datetime,time,boolean,number,string
                var selectionType = variables[i].seltype; // S=Single,M=Multiple,R=Range

                cnt += 1;

                if (selectionType == BOILib.SelectionTypes.Single) {
                    // = value //in case not date
                    // For Date:check js date object reference for methods and
                    // return types..
                    if (type == 'date')
                        value = this.dateToString(value);

                    url += this.Bex7StrFormat(name, cnt, value);

                }

                if (selectionType == BOILib.SelectionTypes.Multiple) {

                    var myvalues = "";

                    if (type == 'date') {
                        for (var x in values) {
                            var myvalue = values[x];
                            myvalues += this.dateToString(myvalue) + ';';
                        }

                    } else {
                        if (typeof values == "string") {
                            myvalues = values;
                        } else {
                            myvalues = values.join(';');
                        }
                    }

                    url += this.Bex7StrFormat(name, cnt, myvalues);

                    // in case of data type is date
                    // For Date:check js date object reference for methods and
                    // return types..
                    // myvalue.getDate() //returns day

                }

                if (selectionType == BOILib.SelectionTypes.Range) {

                    var arrRange = [];
                    for (var r in ranges) {
                        var myrange = ranges[r];
                        if (type == 'date') {

                            var from = this.dateToString(myrange.from);
                            var to = this.dateToString(myrange.to);
                            var operator = myrange.operator;

                            myrange = this.Bex7PatchRangeValue(from, to,
                                operator);

                            arrRange.push(myrange);
                        } else {
                            myrange = this.Bex7PatchRangeValue(myrange.from,
                                myrange.to, myrange.operator);
                            if (myrange == "undefined" || myrange == undefined) {
                                myrange = "";
                            }
                            arrRange.push(myrange);
                        }
                        // myrange.operator
                        // myrange.from
                        // myrange.to...
                        // For Date:check js date object reference for methods
                        // and return types..


                    }

                    {
                        url += this.Bex7StrFormat(name, cnt, arrRange.join(';'));
                    }


                }

            }
            var fullURL = '';// '/irj/servlet/prt/portal/prtroot/pcd!3aportal_content!2fcom.sap.pct!2fplatform_add_ons!2fcom.sap.ip.bi!2fiViews!2fcom.sap.ip.bi.bex?';
            return fullURL + url;
        },

        Bex7StrFormat:function (varName, n, values) {
            var result = "&";
            if (varName && values) {
                result += "BI_COMMAND_" + n
                    + "-BI_COMMAND_TYPE=SET_VARIABLES_STATE&";
                result += "BI_COMMAND_" + n
                    + "-VARIABLE_VALUES-VARIABLE_VALUE_" + n
                    + "-VARIABLE_TYPE=VARIABLE_INPUT_STRING&";
                result += "BI_COMMAND_" + n
                    + "-VARIABLE_VALUES-VARIABLE_VALUE_" + n
                    + "-VARIABLE_TYPE-VARIABLE_INPUT_STRING=";
                result += values + "&" + "BI_COMMAND_" + n
                    + "-VARIABLE_VALUES-VARIABLE_VALUE_" + n + "-VARIABLE=";
                result += varName;

            }

            return result;
        },

        Bex7PatchRangeValue:function (from, to, operator) {
            var op = operator && operator.toLowerCase();
            var result = '';
            if (op == 'bt')
                result = from + this.Bex7ConvertRangeSigns(operator) + to;
            else
                result = this.Bex7ConvertRangeSigns(operator) + from;

            return result;
        },

        Bex7ConvertRangeSigns:function (rs) {

            // before accessing rs methond, make sure it is a valid object.
            var tmp = rs && rs.toString().toLowerCase();
            var signs = {
                "gt":">",
                "ge":">=",
                "lt":"<",
                "le":"<=",
                "bt":" - "
            };

            var result = signs[tmp];

            if (result != undefined)
                return result;
        }
    },

    Util:{
        logWindow:undefined,

        logDialog:undefined,

        timeStamp:function timeStamp() {
            var d = new Date();
            return d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds()
                + ' - ';
        },

        log:function log(entry, isDialog) {
            var output = this.timeStamp() + ': ' + entry + '\r\n\r\n';
            if (this.logWindow) {
                $(this.logWindow).val($(this.logWindow).val() + output);
                var psconsole = $(this.logWindow);
                $(this.logWindow).scrollTop(
                    psconsole[0].scrollHeight - psconsole.height());
            }

            if (isDialog) {
                if (!this.logDialog) {
                    this.logDialog = $(document.createElement('div'));
                }
                this.logDialog.html(entry);
                this.logDialog.dialog();
            }

            return output;
        },
        dialog:function dialog(html, refresh) {
            this.dialog = $(document.createElement('div'));
            this.dialog.html('');
            this.dialog.html(html);
            this.dialog.dialog({
                height:200,
                width:400,
                modal:true,
                resizable:false,
                show:"fast",
                buttons:[
                    {
                        text:"Close",
                        click:function () {
                            $(this).dialog("close");
                        }
                    }
                ]

            });
            this.dialog.dialog('open');
        },

        createDialog:function createDialog(html, title, wd, ht) {
            this.dialog = $(document.createElement('div'));
            this.dialog.html(html);
            this.dialog.dialog({
                title:title,
                height:ht,
                width:400,
                modal:false,
                resizable:false,
                show:"fast",
                autoOpen:false,
                buttons:[
                    {
                        text:"Close",
                        click:function () {
                            $(this).dialog("close");
                        }
                    }
                ]
                // buttons: [{ text: "Close", click: function () {
                // $(this).dialog("close"); } }]
            });
        },
        createIFrameDialog:function createIFrameDialog(page_src, title, wd, ht, startX, startY, callerWindow) {
            page_src = encodeURIComponent(page_src);
            var dlg_height = ht - 9;
            var dlg_width = wd - 10;
            var frm_src = "<iframe frameborder='0' scrolling='no' width='" + dlg_width
                + "px' height='" + dlg_height + "px' "
                + " src='sample_dialog_frame.htm?src=" + page_src
                + "&title=" + title + "' ></iframe>'";

            // VEETTISM,5-Oct-13 :added this line to enable only one dialog at a
            // time
            if (currentDlg) {
                if (currentDlg.dialog('isOpen') == true) {
                    currentDlg.dialog('close');
                }
            }
            // currentDlg.dialog("option", { position: [e.pageX+5,
            // (e.pageY+5)-$(document).scrollTop()] });
            currentDlg = $(document.createElement('div'));
            currentDlg.html(frm_src);

            currentDlg.dialog({
                dialogClass:'noTitleDialog',
                title:title,
                height:ht,
                width:wd,
                modal:false,
                resizable:false,
                show:"fast",
                autoOpen:false,
                draggable:false
            });
            currentDlg.parent().draggable();
            if ((startX >= 0) && (startY >= 0)) {
                currentDlg.dialog("option", {
                    position:[ startX, (startY) - $(document).scrollTop() ]
                });
            }

            if (!currentDlg.dialog("isOpen")) {
                currentDlg.dialog('open');
            }
            if (callerWindow) {
                currentDlg.callerWindow = callerWindow;
            }
        },

        /**
         * MODE MONO: if used, it will show only one dialog at a time. The old
         * one will be disposed StartX and StartY: if not specified, it will
         * show in the center of the window
         */
        createIFrameDialog_Ex:function createIFrameDialog(page_src, title, wd, ht, mode, startX, startY) {
            if (mode == 'MONO') {
                if (currentDlg) {
                    if (closeDialogInternal) {
                        closeDialogInternal(currentDlg);
                    }
                }
            }
            if (!title) {
                title = '';
            }
            var frm_src = "dlg_iframe_content.htm?src="
                + encodeURIComponent(page_src) + "&title=" + title;

            var dlg_id = "dlg_" + Math.floor((Math.random() * 10000) + 1);
            var dlgElem = $(
                "<iframe frameborder='0' scrolling='no' "
                    + " id='"
                    + dlg_id
                    + "' "
                    + " style='display:none;left: 125px; top: 150px; width: 500px; height: 225px; overflow:hidden; position: absolute; z-index:999'src='"
                    + frm_src + "'></iframe>").get(0);

            currentDlg = $(dlgElem);
            currentDlg.attr("name", dlg_id);
            currentDlg.load(function () {
                dlgElem.contentWindow.dlgName = dlg_id;
            });
            $("#dlg_container").append(dlgElem);

            currentDlg.attr("src", "");
            currentDlg.attr("src", frm_src);
            if (wd) {
                currentDlg.css("width", wd);
            }
            if (ht) {
                currentDlg.css("height", ht);
            }
            if (startX) {

                currentDlg.css("left", startX);
            } else {
                var left = (window.innerWidth / 2) - (wd / 2);
                currentDlg.css("left", left);
            }
            if (startY) {
                currentDlg.css("top", startY);
            } else {
                var top = (window.innerHeight / 2) - (ht / 2);
                currentDlg.css("top", top);
            }

            currentDlg.css("display", "block");

        },
        openDialog:function openDialog() {
            this.dialog.dialog('open');
        },
        closeDialog:function closeDialog() {
            this.dialog.dialog('close');
        },

        getUrlParam:function getUrlParam(name) // returns a url parameter
            // value
        {
            name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
            var regexS = "[\\?&]" + name + "=([^&#]*)";
            var regex = new RegExp(regexS);
            var results = regex.exec(window.location.search);
            if (results == null)
                return "";
            else
                return decodeURIComponent(results[1].replace(/\+/g, " "));
        },

        ucwords:function ucwords(str) {
            return str.replace(/\w\S*/g, function (txt) {
                return txt.charAt(0).toUpperCase()
                    + txt.substr(1).toLowerCase();
            });
        },

        getIframeWindow:function getIframeWindow(iframe_object) {
            var doc;

            if (iframe_object.contentWindow) {
                return iframe_object.contentWindow;
            }

            if (iframe_object.window) {
                return iframe_object.window;
            }

            if (!doc && iframe_object.contentDocument) {
                doc = iframe_object.contentDocument;
            }

            if (!doc && iframe_object.document) {
                doc = iframe_object.document;
            }

            if (doc && doc.defaultView) {
                return doc.defaultView;
            }

            if (doc && doc.parentWindow) {
                return doc.parentWindow;
            }

            return undefined;
        },
        getBaseUrlBWAbap:function getBaseUrlBWAbap() {
            return window.location.href.substr(0, window.location.href.indexOf('/bc/bsp/sap/')) + '/bc/bsp/sap/';
        }
    }
};

/**
 * ******************************* BOI Data Access Model
 * *******************************************
 */

var BOIData = {
    debugWindow:null,
    actions:{
        read:"READ",
        update:"UPDATE",
        del:"DELETE",
        create:"CREATE"
    },
    render:{
        loading:function (href) {
            var src = "img/ajax-loader.gif";
            if (href.indexOf('/comp/') > -1)
                src = "../" + src;
            return '<img class="bi_loading" style="position: absolute;" src="'
                + src + '" alt="loading.."/>';
        }
    },
    check:{
        validateRole:function (role, fn) {

            var req = BOIData.request.prepare('ZCL_MYBW_GEN_SERVICES',
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "TYPE":[ "VALIDATE_ROLE" ],
                    "ROLE":[ role ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', function (data) {
                if ($(data).find('STATUS').text() == 'F')
                    fn(false);
                else
                    fn(true);
            });
        }
    },
    read:{
        getApp:function (app_id, fn) {
            var record = BOIData.data.createRecord({
                "APP_ID":[ app_id ],
                "USER_TYPE":[ "ADMIN" ]
            });
            var req = BOIData.request.prepare("ZCL_MYBW_APP_CATALOG",
                BOIData.actions.read, [ record ]);

            BOIData.request.perform(req, "text", "POST", fn);
        },
        getNode:function (app_id, tech_name, fn, debugIn, rep_type, clear_cache) { // TODO: rep_type just added
            var record;
            if (rep_type)
                record = BOIData.data.createRecord({
                    "APP_ID":[ app_id ],
                    "TECH_NAME":[ tech_name ],
                    "REPORT_TYPE":[ rep_type ],
                    "CLEAR_CACHE":[ clear_cache ]
                });
            else
                record = BOIData.data.createRecord({
                    "APP_ID":[ app_id ],
                    "TECH_NAME":[ tech_name ]
                });
            var req = BOIData.request.prepare("ZCL_MYBW_REP_CATALOG",
                BOIData.actions.read, [ record ]);
            if (debugIn)
                debugIn.val(req);
            BOIData.request.perform(req, "text", "POST", fn);

        },
        getTemplate:function (app_id, template_id, fn) {
            var record = BOIData.data.createRecord({
                "APP_ID":[ app_id ],
                "TEMPLATE_ID":[ template_id ]
            });
            var req = BOIData.request.prepare("ZCL_MYBW_VAR_TEMPLATE",
                BOIData.actions.read, [ record ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getView:function (app_id, view_id, fn) {
            var record = BOIData.data.createRecord({
                "APP_ID":[ app_id ],
                "VIEW_ID":[ view_id ]
            });
            var req = BOIData.request.prepare("ZCL_MYBW_VAR_VIEW",
                BOIData.actions.read, [ record ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getComponent:function (app_id, comp_id, fn) {
            var record = BOIData.data.createRecord({
                "APP_ID":[ app_id ],
                "COMP_ID":[ comp_id ]
            });
            var req = BOIData.request.prepare("ZCL_MYBW_COMPONENT",
                BOIData.actions.read, [ record ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getF4:function (app_id, rep_id, rep_type, var_name, format, variables, paging, cycle, page_size, search_term, fn, auto_complete, SEARCH_FLD_NAME) {
            if ((SEARCH_FLD_NAME == undefined) || (SEARCH_FLD_NAME == null)) {
                SEARCH_FLD_NAME = '';
            }
            var record = BOIData.data.createRecord({
                APP_ID:[ app_id ],
                REPORT_ID:[ rep_id ],
                REPORT_TYPE:[ rep_type ? rep_type : "" ], // TODO: JUST ADDED
                VAR_NAME:[ var_name ],
                OUTPUT_TYPE:[ format ? format : 'XML' ],
                READ_MODE:[ 'C' ],
                PAGE_FLAG:[ paging ? 'X' : '' ],
                CYCLE:[ cycle ? cycle : '1' ],
                NO_RECORD:[ page_size ? page_size : '10' ],
                SEARCH:[ search_term ? search_term : '' ],
                VARIABLES:[ variables ? variables : '' ],
                FORMAT:[ 'X' ],
                DISPLAY_KEY:[ '' ],
                TITLE_GROUPING:[ '' ],
                COMBINE_TITLES:[ '' ],
                AUTO_COMPLETE:[ auto_complete ],
                SEARCH_FLD_NAME:[ SEARCH_FLD_NAME ]
            });
            var req = BOIData.request.prepare("ZCL_MYBW_F4",
                BOIData.actions.read, [ record ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getDesigner:function (app_id, fn) {
            var record = BOIData.data.createRecord({
                "APP_ID":[ app_id ]
            });
            var req = BOIData.request.prepare("ZCL_MYBW_COMP_COMPLETE",
                BOIData.actions.read, [ record ]);
            BOIData.request.perform(req, "text", "POST", fn); // TODO: Use
            // when done in
            // backend

            /*
             * $.ajax({ url: "bi_apps_init.xml", data: req, dataType: 'text',
             * success: function(data) { if(fn) fn(data); } });
             */
        }
    },
    list:{
        getApps:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_APP_CATALOG",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "APP_ID":[ app_id ],
                    "OUTPUT_FORMAT":[ "JSON" ],
                    "USER_TYPE":[ "ADMIN" ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getAllApps:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_APP_CATALOG",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "OUTPUT_FORMAT":[ "JSON" ],
                    "USER_TYPE":[ "ADMIN" ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getUserApps:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_GEN_SERVICES",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "TYPE":[ "GET_APPS" ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getCatalog:function (app_id, format, mode, fn, parameters) {
            if (typeof format == 'undefined')
                format = "JSON";
            if (typeof mode == 'undefined')
                mode = "ADMIN";
            var className = "ZCL_MYBW_REP_CATALOG";

            var records = {
                "APP_ID":[ app_id ],
                "OUTPUT_FORMAT":[ format ],
                "USER_TYPE":[ mode ]
            };

            if (parameters != null) {
                if (typeof parameters == "object") {
                    for (var i in parameters) {
                        if (i == "CLASS") {
                            className = parameters[i];
                        } else {
                            records[i] = [ parameters[i] ];
                        }
                    }

                }
            }
            var paramRecords = BOIData.data.createRecord(records);

            var req = BOIData.request.prepare(className, BOIData.actions.read,
                [ paramRecords ]);

            BOIData.request.perform(req, "text", "POST", fn);
        },
        getTemplates:function (app_id, type, fn) {
            if (app_id == undefined)
                app_id = "ALL";
            var req = BOIData.request.prepare("ZCL_MYBW_VAR_TEMPLATE",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "APP_ID":[ app_id ],
                    "TYPE":[ type ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getVariableViews:function (app_id, fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_VAR_VIEW",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "APP_ID":[ app_id ],
                    "VIEW_ID":[ "" ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getComponents:function (app_id, fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_COMPONENT",
                BOIData.actions.read, [ boi_ui.data.createRecord({
                    "APP_ID":[ app_id ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getProperties:function (app_id, comp_id, fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_COMP_PROP",
                BOIData.actions.read, [ boi_ui.data.createRecord({
                    "APP_ID":[ app_id ],
                    "COMP_ID":[ comp_id ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getFavorites:function (app_id, fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_FAVORITES",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "APP_ID":[ app_id ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },

        readUserPreferences: function (type, successfn) {
            var req = BOIData.request.prepare("ZCL_MYBW_PREFERENCES",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "PREF_TYPE":[ type ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", successfn);
        },
        searchBI: function (type, successfn) {
            var req = BOIData.request.prepare("ZCL_MYBW_REP_SEARCH",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "PREF_TYPE":[ type ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", successfn);
        }
    },
    lookup:{
        getConfig:function (context, fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_PARAMETER",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "CONTEXT":[ context ]
                }) ]);
            BOIData.request.perform(req, "text", "POST", fn);
        },
        getNodeTypes:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_PARAMETER",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "CONTEXT":[ 'NODE_TYPE' ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', fn);
        },
        getOpenStyles:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_PARAMETER",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "CONTEXT":[ 'OPEN_STYLE' ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', fn);
        },
        //added by otaism2a to bring all componenet types from the backend
        getCompTypes:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_GEN_SERVICES",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "TYPE":[ 'GET_COMP_TYPES' ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', fn);
        },
        getF4Modes:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_PARAMETER",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "CONTEXT":[ 'F4_MODE' ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', fn);
        },
        getSelectionTypes:function (fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_PARAMETER",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "CONTEXT":[ 'SEL_TYPE' ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', fn);
        },
        getQueryHeader:function (query, fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_GEN_SERVICES",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "TYPE":[ 'GET_QUERY_HEADER' ],
                    "QUERY":[ query ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', fn);
        },
        getVariableDetails:function (query, fn) {
            var req = BOIData.request.prepare("ZCL_MYBW_GEN_SERVICES",
                BOIData.actions.read, [ BOIData.data.createRecord({
                    "TYPE":[ 'GET_VARIABLE_DET' ],
                    "QUERY":[ query ]
                }) ]);
            BOIData.request.perform(req, 'text', 'POST', fn);
        }
    },
    app_id:'ALL',
    request:{
        prepare:function (class_name, method_name, records) {
            var request = "<DATA>";

            for (var i in records) {
                records[i].app_id = BOIData.app_id;
                records[i].class_name = class_name;
                records[i].method_name = method_name;
                request += records[i].toString();
            }
            request += '</DATA>';
            return BOIData.util.htmlToXml(request);
        },
        perform:function (request, datatype, method, successFunction) {
            request = '<?xml version="1.0"?>' + request;
            var url = window.location.href;
            var ajaxurl = url.substr(0, url.indexOf('/bc/bsp/sap/'))
                + "/bc/bsp/sap/zbi_integration/model/bi_app_factory.xml";
            // if(url.indexOf('/comp/') > -1) ajaxurl = '../' + ajaxurl;

            var reqStr = '\n\n************* BEGIN REQUEST ******************\n\n'
                + request.replace(/></g, '>\n<')
                + '\n\n************* END REQUEST ******************\n\n';
            if (BOIData.debugWindow)
                BOIData.debugWindow.val(BOIData.debugWindow.val() + reqStr);

            $
                .ajax({
                    url:ajaxurl,
                    data:request,
                    type:method,
                    contentType:'multipart/form-data',
                    dataType:datatype,
                    success:function (data) {
                        data = data.replace('<PARAM', '<PARAMETER');
                        data = data.replace('</PARAM', '</PARAMETER');
                        data = data.replace('<response', '<RESPONSE');
                        data = data.replace('</response', '</RESPONSE');

                        var output = "";
                        if (datatype == 'xml' || BOIData.util.isXML(data)) {
                            if (document.addEventListener) {
                                // alert("you got IE9 or greater");
                                data = $('<div/>').append(data).html();
                                output = $(data).html();
                                // data = $.parseXML(data);
                            } else {
                                // data = $('<div/>').append(data).html();
                                // output = $(data).html();
                                data = $.parseXML(data);
                            }
                        } else
                            output = data.replace(/></g, '>\n<');

                        var respStr = '\n\n************* BEGIN RESPONSE ******************\n\n'
                            + output
                            + '\n\n************* END RESPONSE ******************\n\n';
                        if (BOIData.debugWindow)
                            BOIData.debugWindow.val(BOIData.debugWindow
                                .val()
                                + respStr);

                        if (datatype == 'xml'
                            && $(data).find('STATUS').get(0)) {
                            if ($(data).find('STATUS').text() == 'F')
                                alert($(data).find('MESSAGE').text());
                            else if (successFunction) {
                                try {
                                    successFunction(data);
                                } catch (e) {
                                    BOILib.Util.log(e.name + ":"
                                        + e.message, true);
                                }
                            }
                        } else {
                            if (successFunction) {
                                try {
                                    successFunction(data);
                                } catch (e) {
                                    BOILib.Util.log(e.name + ":"
                                        + e.message, true)
                                }
                            }
                        }
                    },
                    error:function (xhr, ajaxOptions, thrownError) {
                        var respStr = '\n\n************* BEGIN RESPONSE ******************\n\n'
                            + '\n\n--- Status ---\n\n'
                            + xhr.status
                            + ', ERROR: '
                            + thrownError
                            + ', RESPONSE:\n\n'
                            + xhr.responseText
                            + '\n\n************* END RESPONSE ******************\n\n';
                        if (BOIData.debugWindow)
                            BOIData.debugWindow.val(BOIData.debugWindow
                                .val()
                                + respStr);

                        alert('Error: Request '
                            + $(request).find('CLASS_NAME').text()
                            + '.' + $(request).find('METH_NAME').text()
                            + ' Failed with Server Status '
                            + xhr.status + ': ' + thrownError);
                        // console.log(xhr.status + '\n\n' + request +
                        // '\n\n'+ xhr.responseText + '\n\n'+ thrownError);
                    }
                });
        }
    },
    data:{
        createRecord:function (params) { // create from hashset
            var record = new BOIData.Record();
            for (var i in params) {
                var param = new BOIData.Parameter();
                param.name = i;
                for (var v in params[i])
                    param.values.push(params[i][v]);

                record.parameters.push(param);
            }
            return record;
        }
    },
    util:{
        htmlToXml:function (request) {
            // convert html to XML (handling capitalization)
            var pattern = /<([\/]*)([a-zA-Z_0-9]+)([^>]*)>/g;

            request = request.replace(pattern, function (full, before, tag, after) {
                return "<" + before + tag.toUpperCase() + after + ">"
            });

            return request;
        },
        htmlEncode:function (str) {
            return String(str).replace(/&/g, '&amp;').replace(/"/g, '&quot;')
                .replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g,
                    '&gt;');
        },
        htmlDecode:function (text) {
            var decoded = $('<div/>').html(text).text();
            return decoded;
        },
        getParameterByName:function (querystring, name) {
            name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
            var regexS = "[\\?&]" + name + "=([^&#]*)";
            var regex = new RegExp(regexS);
            var results = regex.exec(querystring);
            if (results == null)
                return "";
            else
                return decodeURIComponent(results[1].replace(/\+/g, " "));
        },
        isXML:function (text) {
            var isXml = true;
            try {
                isXml = $.parseXML(text);
            } catch (e) {
                isXml = false;
            }
            return isXml;
        }
    },
    Record:function () {
        this.app_id = "ALL";
        this.class_name = "";
        this.method_name = "";
        this.parameters = [];

        this.toString = function () {
            var output = "<RECORD><CLASS_NAME>" + this.class_name
                + "</CLASS_NAME><METH_NAME>" + this.method_name
                + "</METH_NAME><APP_ID>" + this.app_id + "</APP_ID>";
            for (var i in this.parameters)
                output += this.parameters[i].toString();
            output += '</RECORD>';
            return BOIData.util.htmlToXml(output);
        };
    },
    Parameter:function () {
        this.name = "";
        this.values = [];
        this.toString = function () {
            var output = "<PARAMETER><NAME>" + this.name + "</NAME>";
            // var values = $('');
            for (var i in this.values)
                output += '<VALUES><VALUE>'
                    + BOIData.util.htmlEncode(this.values[i])
                    + '</VALUE></VALUES>';

            if (this.values.length == 0)
                output += '<VALUES><VALUE></VALUE></VALUES>';
            output += '</PARAMETER>';
            return BOIData.util.htmlToXml(output);
        };
    }
};
var boi_ui = BOIData;

/*
 * BOI Singleton Instance
 * **************************************************************
 */

/* IMPORTANT: required initialization is done at end of this file */
var currentDlg;

var BOI = {
    single_variable_screen:true,
    debugMode:true,
    log:BOILib.Util.log('BOI Object Ready.'),
    context:new BOILib.Context(), // Storage of current context
    urlForServer:"sbo.aramco.com.sa",
    protocolForBOServer:"https://",
    urlForOpenDocument:"",
    urlForBex3:"",
    urlForBex7:"",
    urlForReportCatalogXML:"",
    urlForReportCatalogJSON:"",
    urlForReportMeta:"",
    urlForVariableF4:"",
    urlForVariableF4Query:"",
    urlForVariableF4Paging:"",
    urlForVariableF4Search:"",
    app_id:undefined,
    doc:document,
    favorites:{},
    app_params:{},
    home_report:undefined,
    remove_home:undefined,
    // 16/2/2014 Ansaj Added for theme configuration
    add_theme:undefined,
    displayLog:function (logData) {
        BOILib.Util.log(logData, true);
    },
    //Added by jaroudnh 2/9/2014 a prompt that can be used any where...
    //if default_value = false... don't show input field. on 2/16/2014
    boiPrompt:function boiPrompt(title, message, default_value, ok_function, cancel_function) {
        var dialog_box = '' +
            '<div id="dialog-confirm" title="{0}">' +
            '<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>{1}</p>';
        if (default_value != false) {
            dialog_box += '<input type="text" id="rprt_name" value="{2}" />';
            dialog_box = dialog_box.replace("{2}", default_value);
        }
        dialog_box += '</div>';

        dialog_box = dialog_box.replace("{0}", title);
        dialog_box = dialog_box.replace("{1}", message);

        $(dialog_box).dialog({
            resizable:false,
            height:150,
            modal:true,
            buttons:{
                "Ok":function () {
                    $(this).dialog("close");
                    if (default_value != false)
                        ok_function($('#rprt_name').val());
                    else
                        ok_function();
                    $(this).html("");
                },
                Cancel:function () {
                    $(this).dialog("close");
                    cancel_function;
                    $(this).html("");
                }
            }
        });
    },
    addDebugLog:function (logData, displayLog) {
        if (parent.debugMode)
            BOI.log += BOILib.Util.log(logData, displayLog);
    },
    callback:function (parentFn, childFn) {
        parentFn();
        childFn();
    },
    setLogWindow:function (window) // can be attached to a text area for
        // example to show log messages
    {
        BOILib.Util.logWindow = window;
    },

    loadReportCatalog:function (dashboard, format, successFunction, mode, parameters, reload) // uses urlForReportCatalog to return Reports
        // Hierarchy XML/JSON
    {
        if (mode == undefined)
            mode = 'USER'; // default
        // populates context's navigation reportCatalog attribute xml
        // this function should be called only once. To access the catalog use
        // BOI.context.reportCatalog
        // execute ajax call
        this.app_id = dashboard;

        var parent = this;
        this.context.parent = this;

        // always populate context using xml
        BOI.addDebugLog('loadReportCatalog(...), Loading Catalog for '
            + dashboard + ' using ' + format);

        BOIData.list.getCatalog(dashboard, 'XML', mode, function (data) {

            if (parent.debugMode)
                BOI.log += BOILib.Util.log('XML Report Catalog Loaded for '
                    + dashboard + ' using ' + format);
            // on success return the xml and store it in
            // this.context.navigation.reportCatalog
            parent.context.reportCatalog = data;
            if (!parent.context.variables) {
                parent.context.variables = {};
            }
            // parent.context.variables = {};
            if (parent.debugMode)
                BOI.log += BOILib.Util.log('Start Populating Context');
            parent.context.populateCatalog(reload); // converts xml into actual
            // report objects
            if (format == BOILib.OutputTypes.XML) {
                if (successFunction)
                    successFunction(data); // execute caller desired function for
                // whatever purpose..
                return data; // returns xml
            } else {
                if (parent.debugMode)
                    BOI.log += BOILib.Util.log('Loading JSON Catalog');
                // ajax call for json format
                BOIData.list.getCatalog(dashboard, format, mode,
                    function (data) {
                        if (parent.debugMode)
                            BOI.log += BOILib.Util
                                .log('JSON Catalog Loaded');
                        parent.context.reportCatalogTree = jQuery
                            .parseJSON(data.replace(/isBranch/g,
                                "isFolder"));
                        parent.context.reportCatalogJSON = jQuery
                            .parseJSON(data);
                        // console.log(data);
                        if (successFunction)
                            successFunction(data); // execute caller desired
                        // function for whatever
                        // purpose..
                        return data; // returns json

                    }, parameters);
            }
        }, parameters, reload);
    },

    //otaism2a : added this function to return the report type
    checkReportType:function (report_type) {

        switch (report_type) {
            case BOILib.ReportTypes.Bex3:
                report_type = "BW_BEX3";
                break;
            case BOILib.ReportTypes.Bex7:
                report_type = "BW_BEX7";
                break;
            case BOILib.ReportTypes.Crystal:
                report_type = "BO_CRYSTAL";
                break;
            case BOILib.ReportTypes.Webi:
                report_type = "BO_WEBI";
                break;
            case BOILib.ReportTypes.Xcelsius:
                report_type = "BO_DASHBOARD";
                break;
            case BOILib.ReportTypes.XcelsiusLocal:
                report_type = "BW_DASHBOARD";
                break;
            case BOILib.ReportTypes.URL:
                report_type = "URL";
                break;
            case BOILib.ReportTypes.DesignStudio:
                report_type = "BO_DESIGN";
                break;
            case BOILib.ReportTypes.Flash:
                report_type = "FLASH";
                break;
        }
        return report_type;


    },
    // otaism2a : 9/2/2014 added to reduce the line of code for kpi loading
    loadKpiDrillDown:function (definition, kpi) {


        kpi.DRILL_DOWNS = new Array();

        definition.find("DRILL_DOWN").each(function () {
            var tempDrilldown = new Object();
            var drilldonwXML = this;
            tempDrilldown.SOURCE_COLUMN = $(drilldonwXML).find('SOURCE_COLUMN').text();
            tempDrilldown.TARGET_BO = $(drilldonwXML).find('TARGET_BO').text();
            tempDrilldown.TARGET_QUERY = $(drilldonwXML).find('TARGET_QUERY').text();
            tempDrilldown.MAPPINGS = new Array();

            $(drilldonwXML).find('MAPPING').each(function () {
                var mappingXML = this;
                var tempMapping = new Object();
                tempMapping.TECHNAME = $(mappingXML).find('TECHNAME').text();
                tempMapping.NAME = $(mappingXML).find('NAME').text();
                tempMapping.IOBJNM = $(mappingXML).find('IOBJNM').text();
                tempMapping.MAPPED_VALUE = $(mappingXML).find('MAPPED_VALUE').text();
                tempMapping.VALUE = $(mappingXML).find('VALUE').text();
                tempMapping.AXIS = $(mappingXML).find('AXIS').text();
                tempDrilldown.MAPPINGS.push(tempMapping);
            });
            kpi.DRILL_DOWNS.push(tempDrilldown);
        });

        return kpi.DRILL_DOWNS;

    },
    loadReportMeta:function (report, successFunction, clear_cache, tech_name) // populate
        // report
        // with
        // variables
        // information
    {
        var parent = this;
        var report_type = undefined;

        if (tech_name) {
            report = new BOILib.Report();
            report.tech_name = tech_name;
            report.report_type = undefined; // we will force the server to get the report type

        }
        report_type = report.type;

        if (parent.debugMode)
            BOI.log += BOILib.Util
                .log('BOI.loadReportMeta(...), Loading Variable Information for report '
                    + '(' + report.tech_name + ')');


        BOIData.read
            .getNode(
            parent.app_id,
            report.tech_name,
            function (data) {

                // on success return the xml and store it in for the
                // current report object
                report.metadata = data;

                if (parent.debugMode)
                    BOI.log += BOILib.Util.log('Variables Loaded');

                if (tech_name) {

                    report.id = $(report.metadata).find(
                        'NODE_INFO NODE_ID').text();

                    report.type = $(report.metadata).find(
                        'NODE_INFO NODE_TYPE').text();
                    report.label = $(report.metadata).find(
                        'NODE_INFO TITLE').text();
                    report.parent_id = $(report.metadata).find(
                        'NODE_INFO PARENT_ID').text();
                    BOI.context.reports[report.id] = report;
                }

                //otaism2a : check for report types , "BW_BEX3 /BEX7 /CRYSTAL ..etc
                report_type = BOI.checkReportType(report_type);

                var varnames = "";
                var count = 0;

                report.description = $(report.metadata).find(
                    'NODE_INFO DESCRIPTION').text();
                report.VARIABLE_SCREEN = $(report.metadata).find(
                    'NODE_INFO VARIABLE_SCREEN').text() == 'X';
                report.KPI_DRL_DOWN_URL = $(report.metadata).find(
                    'NODE_INFO KPI_DRL_DOWN_URL').text();
                var openStyle = $(report.metadata).find(
                    'LAYOUT_INFO OPEN_STYLE').text();
                report.QUERY_TEMPLATE = $(report.metadata).find(
                    'QUERY_TEMPLATE').text();

                // this check is required, to maintain the
                // OPEN_STYLE(aka target frame) which is set in the
                // getCatalog XML
                if (openStyle) {
                    report.OPEN_STYLE = openStyle;
                }
                report.DATA_PROVIDER = $(report.metadata).find(
                    'LAYOUT_INFO DATA_PROVIDER').text();

                if (report_type == "REPORT_GROUP") {
                    // fill in reports layout
                    if ($(report.metadata).find('REPORTS_LAYOUT')
                        .text().length > 0)
                        report.replayout = $(report.metadata).find(
                            'REPORTS_LAYOUT').html();
                }

                if (report_type == "KPI") {
                    var definition = $(report.metadata).find(
                        'REP_DEFINITION').text();
                    definition = $(definition);
                    var kpi = {
                        Y_AXES:{}
                    };

                    kpi.X_AXIS = definition.find('X_AXIS').text();
                    kpi.SERIES_AXIS = definition
                        .find('SERIES_AXIS').text();
                    kpi.PLOT_TYPE = definition.find('PLOT_TYPE')
                        .text();
                    kpi.CHART_TYPE = definition.find('CHART_TYPE')
                        .text();

                    definition
                        .find('Y_AXES Y_AXIS')
                        .each(
                        function () {
                            kpi.Y_AXES[$(this).text()] = $(
                                this).text();
                        });

                    report.kpi = kpi;
                }

                // fill in variables layout
                if ($(report.metadata).find('VARIABLES_LAYOUT')
                    .text().length > 0)
                //$('<div/>').html(text).text();

                // Now we need to decode the data
                //Assign to varlayout variable.
                    report.varlayout = $(report.metadata).find('VARIABLES_LAYOUT').text();


                //report.varlayout = $('<div/>').html(encoded_text).text();

                //  report.varlayout = $(report.metadata).find(
                //    'VARIABLES_LAYOUT').

                // fill in variables
                $(report.metadata)
                    .find('ZBUS_VAR_META')
                    .each(
                    function () {
                        var variable = new BOILib.Variable();
                        variable.name = $(this).find(
                            "ZVARNAME").text(); // ZVARNAME
                        variable.description = $(this)
                            .find(
                                "ZVAR_DESCRIPTION")
                            .text(); // ZVAR_DESCRIPTION
                        variable.type = "string"; //
                        variable.value = $(this).find(
                            "DEF_VAL").text(); // DEF_VAL
                        variable.seltype = $(this)
                            .find("SEL_TYPE")
                            .text(); // DEF_VAL
                        variable.display = $(this)
                            .find('ZDISPLAY')
                            .text();
                        variable.f4type = $(this).find(
                            'F4_MODE').text();
                        variable.f4query = $(this)
                            .find('F4_QUERY')
                            .text();
                        variable.group = $(this).find(
                            'VAR_GRP').text();
                        variable.location = $(this)
                            .find('VAR_LOC').text();

                        variable.VARTYP = $(this).find(
                            'VARTYP').text();
                        variable.VPROCTP = $(this)
                            .find('VPROCTP').text();
                        variable.ENTRYTP = $(this)
                            .find('ENTRYTP').text();
                        variable.SEL_TYPE = $(this)
                            .find('SEL_TYPE')
                            .text();
                        variable.IOBJNM = $(this).find(
                            'IOBJNM').text();
                        variable.DEF_VAL = $(this)
                            .find('DEF_VAL').text();
                        variable.URL_PARAM = $(this)
                            .find('URL_PARAM')
                            .text();

                        if (variable.name) {
                            count++;
                            /*
                             * if(parent.context.variables[variable.name]) {
                             * //already in context
                             * report.variables[variable.name] =
                             * parent.context.variables[variable.name]; }
                             * else
                             */
                            {
                                // add to report
                                report.variables[variable.name] = variable;
                            }
                        }
                    });

                // set dependencies
                var deps = $(report.metadata).find(
                    'LAYOUT_INFO VAR_DEPENDS').text();
                if (deps != "") {
                    deps = deps.split('|');

                    for (var i in deps) {
                        if (deps[i]) {
                            var tmp = deps[i].split("=");
                            var vname = tmp[0];
                            var vdeps = tmp[1].split('&');

                            var v = report.variables[vname];

                            if (v)
                                for (var dp in vdeps)
                                    if (vdeps[dp]
                                        && report.variables[vdeps[dp]])
                                        v.dependencies[vdeps[dp]] = report.variables[vdeps[dp]];

                        }
                    }
                }
                // add the variable to context
                for (var i in report.variables) {
                    if (report.variables[i])
                        if (parent.context.variables[report.variables[i].name] === undefined) {
                            // add the variable to context
                            parent.context.variables[report.variables[i].name] = report.variables[i];

                            // reference to current report
                            parent.context.lastReport = report;
                        }
                        else
                        {
                            report.variables[i].value = parent.context.variables[report.variables[i].name].value;
                            report.variables[i].values = parent.context.variables[report.variables[i].name].values;
                        }
                }

                if (parent.debugMode)
                    BOI.log += BOILib.Util
                        .log('Done Populating Context with '
                            + count + ' variables');

                if (successFunction)
                    successFunction(report);

                BOI.Designer.showHideComponents(report.id);
                return report;
            }, undefined, report_type, clear_cache);
    },

    loadFavorites:function (app_id, successFunction) {
        var reports = {};
        if (app_id == undefined)
            app_id = BOI.app_id;
        BOIData.list
            .getFavorites(
            app_id,
            function (data) {
                $(data)
                    .find('FAVORITE')
                    .each(
                    function () {
                        var report = new BOILib.Report();
                        report.id = $(this).find(
                            'NODE_ID').text();
                        report.tech_name = $(this)
                            .find('REPORT_ID')
                            .text();
                        report.label = $(this).find(
                            'FAV_TITLE').text();
                        report.type = $(this).find(
                            'NODE_TYPE').text();
                        report.app_id = $(this).find(
                            'APP_ID').text();

                        var varsXml = BOIData.util
                            .htmlDecode($(this)
                                .find('CONTEXT')
                                .text());
                        /*
                         * <REPORT_CONTEXT> <VARIABLE>
                         * <NAME></NAME> <SEL_TYPE>M</SEL_TYPE>
                         * <VALUES> <VALUE></VALUE>
                         * <VALUE></VALUE> </VALUES>
                         * </VARIABLE> </REPORT_CONTEXT>
                         */

                        $(varsXml)
                            .find('VARIABLE')
                            .each(
                            function () {
                                var name = $(
                                    this)
                                    .find(
                                        'NAME')
                                    .text();
                                report.variables[name] = new BOILib.Variable();
                                report.variables[name].seltype = $(
                                    this)
                                    .find(
                                        'SEL_TYPE')
                                    .text(); // SINGLE
                                if (report.variables[name].seltype == 'S')
                                    report.variables[name].value = $(
                                        this)
                                        .find(
                                            'VALUES VALUE')
                                        .text(); // SINGLE
                                else // M
                                {
                                    report.variables[name].values = [];
                                    $(this)
                                        .find(
                                            'VALUES VALUE')
                                        .each(
                                        function () {
                                            report.variables[name].values
                                                .push($(
                                                    this)
                                                    .text());
                                        });
                                    report.variables[name].value = report.variables[name].values;
                                }
                            });
                        reports[report.id] = report;
                    });

                BOI.favorites = reports;

                if (successFunction)
                    successFunction(reports);

                return reports;
            });
    },

    loadF4Values:function (varname, cycle, records, successFunction, report_id, term, format, paging, report_type, auto_complete, SEARCH_FLD_NAME) {
        // returns paginated variable F4 values
        // Multiple calls to this function with different cycles will not
        // aggregate the values. Instead,
        // it will return the last retrieved set only. This is for performance
        // consideration.

        var parent = this;
        if (parent.app_id == undefined)
            parent.app_id = 'ALL';
        if (report_id == undefined)
            report_id = 'ALL';
        if (format == undefined)
            format = 'XML';
        if (auto_complete == undefined)
            auto_complete = "";
        else
            auto_complete = auto_complete ? "X" : "";
        paging = (paging == undefined) ? true : paging;
        cycle = typeof cycle !== 'undefined' ? cycle : 1; // use defaults if
        // not specified
        records = typeof records !== 'undefined' ? records : 100; // use
        // defaults
        // if not
        // specified

        if (this.context.variables[varname]) // if in context
        {
            if (this.context.variables[varname].f4type == BOILib.F4Modes.BWReport) // require
            // execution
            {
                var v = this.context.variables[varname];
                var varsSyntax = ""; // use for dependency
                var depcount = 0;
                for (var i in v.dependencies)
                    if (v.dependencies[i])
                        depcount++;

                if (depcount > 0)
                    varsSyntax += BOILib.BexSyntax.getBex3URL("",
                        v.dependencies);
            }
        }


        //otaism2a : added to check the report type
        report_type = BOI.checkReportType(report_type);


        BOIData.read.getF4(parent.app_id, report_id, report_type, varname,
            format, varsSyntax, paging, cycle, records, term,
            function (data) {

                var f4set = new BOILib.F4Set();
                f4set.url = "";
                f4set.varname = varname;
                f4set.cycle = cycle;
                f4set.records = records;

                f4set.total = format == 'XML' ? $(data).find('TOTAL_REC')
                    .text()
                    : $.parseJSON(data).VALUES_TABLE_C.TOTAL_REC;

                if (format == 'XML')
                    $(data).find('IHTTPNVP').each(function () {
                        var f4 = new BOILib.F4();
                        f4.name = $(this).find('NAME').text();
                        f4.value = $(this).find('VALUE').text();
                        f4set.values[f4.value] = f4;
                    });
                else
                    f4set.json = data;

                if (successFunction)
                    successFunction(f4set); // key/value pairs hashset is
                // inside f4set object's values
                // attribute

                return f4set;
            }, auto_complete, SEARCH_FLD_NAME);
    },

    createReport:function (id, type) {
        var report = new BOILib.Report();
        report.id = id;
        report.tech_name = id;
        report.type = type;
        switch (type) {
            case BOILib.ReportTypes.Bex7:
                report.url = this.urlForBex7;
                break;
            case BOILib.ReportTypes.BO:
            case BOILib.ReportTypes.Crystal:
            case BOILib.ReportTypes.Webi:
            case BOILib.ReportTypes.Xcelsius:
            case BOILib.ReportTypes.DesignStudio:
                report.url = 'http://' + this.urlForServer + '/'
                    + this.urlForOpenDocument + id;
                break;
            case BOILib.ReportTypes.Bex3:
                report.url = this.urlForBex3;
                break;
            case BOILib.ReportTypes.Analysis:
            case BOILib.ReportTypes.Explorer:
            case BOILib.ReportTypes.XcelsiusLocal:
            case BOILib.ReportTypes.URL:
            case BOILib.ReportTypes.Flash:
            default:
                report.url = id;
                break;
        }

        this.context.reports[report.id] = report;

        return report;
    },

    getContextReport:function (id, tech_name) // returns a report object
        // matching the provided id
    {
        return this.context.reports[id];
    },

    getContextReportByTechname:function (tech_name) // returns a report
        // object matching the
        // provided id
    {
        for (var i in this.context.reports)
            if (this.context.reports[i].tech_name == tech_name)
                return this.context.reports[i];

        return undefined;
    },
    getContextReportByTitle:function (title) // returns a report object
        // matching the provided id
    {
        for (var i in this.context.reports)
            if (this.context.reports[i].label == title)
                return this.context.reports[i];

        return undefined;
    },

    createContextVariable:function (name, value, type, seltype, report) // creates
        // a
        // context
        // variable
        // and
        // if
        // already
        // exists,
        // updates
        // it
    {
        if (typeof value != "object")
            value = value + ""; // ensure string format for numbers and boolean

        if (value instanceof Array) {
            // alert('value is Array!');
            var varstr = "";
            for (var i in value)
                if (value[i])
                    if (i < value.length - 1)
                        varstr += value[i] + ',';
                    else
                        varstr += value[i];

            value = varstr;
        }

        // all reports viewing state become obsolete due to the new variable
        // value change
        if (BOI.single_variable_screen) {
            for (var i in this.context.reports) {
                if (this.context.reports[i].variables) {
                    if (this.context.reports[i].variables[name]) {
                        this.context.reports[i].state = BOILib.ReportStates.RefreshNeeded;
                        this.context.reports[i].variables[name].value = value;
                    }
                }
            }
        }

        var variable = new BOILib.Variable();

        if (this.context.variables[name]) {
            variable = this.context.variables[name];
        } else {
            variable.name = name;
            variable.URL_PARAM = name;
        }

        if (type) {
            variable.type = type; // date etc
        } else {
            variable.type = BOILib.VariableTypes.String; // default
        }

        if (seltype) {
            variable.seltype = seltype; // M=multi,R=range,S=single
        } else {
            variable.seltype = BOILib.SelectionTypes.Single; // default
        }

        var isString = value != undefined && value != null
            && type != BOILib.VariableTypes.Date
            && type != BOILib.VariableTypes.DateTime;
        // put data in a proper way
        switch (seltype) {
            default:
            case BOILib.SelectionTypes.Single:
                variable.value = value;
                break;
            case BOILib.SelectionTypes.Multiple:
                variable.values.length = 0;
                if (isString && value.indexOf(',') > -1) {
                    variable.values = value.split(','); // supplied values must be
                    // separated by commas e.g.
                    // 1,2,3
                } else {
                    if (isString)
                        variable.values.push(value);// supplied values is only one
                    // entry
                }

                break;
            case BOILib.SelectionTypes.Range:
                var entries = [];
                var ranges = [];
                if (isString && value.indexOf(',') > -1) {
                    entries = value.split(','); // supplied value must be an array
                    // of range objects e.g.
                    // [1..3),(10..12)
                    for (var i in entries) {
                        var range = new BOILib.Range();
                        range.from = entries[i].split('..')[0].substr(1);
                        range.fromMode = entries[i].substr(0, 1); // from bracket:
                        // ( or [
                        range.to = entries[i].split('..')[1].replace("]", "")
                            .replace(")", "");
                        range.toMode = entries[i].substr(entries[i].length - 1, 1); // to
                        // bracket:
                        // ) or
                        // ]
                        ranges.push(range);
                    }
                } else if (isString) // single range
                {
                    var range = new BOILib.Range();
                    range.from = value.split('..')[0].substr(1);
                    range.fromMode = value.substr(0, 1); // from bracket: ( or [
                    range.to = value.split('..')[1].replace("]", "").replace(")",
                        "");
                    range.toMode = value.substr(value.length - 1, 1); // to
                    // bracket:
                    // ) or ]
                    ranges.push(range);
                }
                variable.ranges = ranges;
                break;
        }
        // variable can be associated to an existing report if needed
        if (report)
            report.variables[name] = variable;

        this.context.variables[name] = variable;
        if (parent.debugMode)
            BOI.log += BOILib.Util
                .log('BOI.createContextVariable(...), Created Context Variable '
                    + variable.name + ' ');

        return variable;
    },

    setContextVariable:function (name, value, type, seltype, report) // sets
        // a
        // value
        // for a
        // context
        // variable;
        // creates
        // the
        // variable
        // if
        // variable
        // does
        // not
        // exist
    {
        return this.createContextVariable(name, value, type, seltype, report);
    },

    getContextVariable:function (varname) // returns a variable object.
    {
        return this.context.variables[varname];
    },

    openFavorite:function (favorite, target) {
        var report = BOI.context.reports[favorite.id];
        if (report == undefined) {
            report = BOI.createReport(favorite.id, favorite.type);
            BOI.app_id = favorite.app_id;
        }

        BOI.loadReportMeta(report, function (rep) {
            // set values
            for (var i in favorite.variables) {
                var variable = favorite.variables[i];
                report.variables[i].value = variable.value;
                report.variables[i].values = variable.values;
            }
            BOI.openReport(report.id, report.type, undefined, true, target);
        });
    },

    openReport:function (id, type, vars, reportVarsOnly, target, refresh, successFunction, contextDocument) {
        // returns the complete report url (including variable values), type and
        // vars are optional
        // bex7 special case
        // if(type == BOILib.ReportTypes.Bex7 || type == "BW_BEX7") target =
        // '_blank';

        contextDocument = typeof contextDocument == 'undefined' ? document
            : contextDocument;

        refresh = typeof refresh !== 'undefined' ? refresh : true; // use
        // defaults
        // if not
        // specified

        target = typeof target !== 'undefined' ? target : '_blank'; // use
        // defaults
        // if not
        // specified

        var parent = this;
        var report; // current report
        var url = ""; // output
        var varsSet = {};

        if (parent.debugMode)
            BOI.log += BOILib.Util.log('BOI.openReport(...), Opening Report '
                + id + ' of type ' + type + ' into target ' + target);

        if (typeof vars == 'string' || vars instanceof String) {
            // if vars is a string, it must be of this form
            // (OpenDocumentSyntax):
            // &lsSVAR_1=9999&lsMVAR_2=aa;bb;cc&lsRVAR_3=[2000..2008)&lsSMyDate=
            // Date(2010,11,16)&lsMDates=Date(2000,5,19);Date(2012,12,20)&lsRDateRange=[Date(2010,3,8)..Date(2005,9,23)]&...

            // reverse parsing of open-document syntax into javascript objects

            // breakdown by ampersand (&)
            var params = vars.split('&');

            var tempVar;

            for (var p in params) {
                if (params[p].indexOf('=') > -1) {
                    // break each by (=)
                    var typename = params[p].split('=')[0];
                    var wholevalue = params[p].split('=')[1];
                    var pname = typename.substr(3);
                    var ptype = typename.substr(0, 3); // selection type
                    var vtype = wholevalue.indexOf('Date(') == 0 ? BOILib.VariableTypes.Date
                        : BOILib.VariableTypes.String;
                    var pvalue = wholevalue;
                    // Determine the type lsS,lsM, or lsR
                    switch (ptype) {
                        // if lsS
                        case "lsS":
                            // Determine the value data type: if it contains "Date("
                            // then it is a date variable,
                            // otherwise it is a string
                            if (wholevalue.indexOf('Date(') == 0) {
                                // if date, get the value and convert it into JS
                                // Date
                                var dateCommaSeparated = wholevalue.replace(
                                    'Date(', '').replace(')', ''); // results
                                // in
                                // yyyy,m,d
                                var parts = dateCommaSeparated.split(',');
                                pvalue = new Date(parts[0], parts[1], parts[2]);
                                vtype = BOILib.VariableTypes.Date;
                            }
                            tempVar = this.createContextVariable(pname, pvalue,
                                vtype, BOILib.SelectionTypes.Single);
                            break;
                        // if lsM,
                        case "lsM":
                            // breakdown values by (;)
                            var entries = pvalue.split(';');
                            tempVar = this.createContextVariable(pname, null,
                                vtype, BOILib.SelectionTypes.Multiple);
                            // for each value
                            for (var v in entries) {
                                var val = entries[v];
                                // Determine the value data type: if it contains
                                // "Date(" then it is a date variable,
                                // otherwise it is a string
                                if (val.indexOf('Date(') == 0) {
                                    // if date, get the value and convert it into JS
                                    // Date
                                    var dateCommaSeparated = val.replace('Date(',
                                        '').replace(')', '');
                                    // results in yyyy,m,d
                                    var parts = dateCommaSeparated.split(',');
                                    val = new Date(parts[0], parts[1], parts[2]);
                                }
                                tempVar.values.push(val);
                            }
                            break;
                        // if lsR, breakdown by (..)
                        case "lsR":
                            // pull out the enclosures
                            var encStart = pvalue.substr(0, 1); // first bracket
                            var encClose = pvalue.substr(pvalue.length - 1, 1); // last
                            // bracket

                            var from = pvalue.split('..')[0].substr(1);
                            var to = pvalue.split('..')[1];
                            to = to.substr(0, to.length - 1);

                            // Determine the value datatype: if it contains "Date("
                            // then it is a date variable, otherwise it is a string
                            if (from.indexOf('Date(') == 0) {
                                vtype = BOILib.VariableTypes.Date;
                                // if date, get the value and convert it into JS
                                // Date
                                var dateCommaSeparated = from.replace('Date(', '')
                                    .replace(')', ''); // results in yyyy,m,d
                                var parts = dateCommaSeparated.split(',');
                                from = new Date(parts[0], parts[1], parts[2]);
                            }
                            if (to.indexOf('Date(') == 0) {
                                // if date, get the value and convert it into JS
                                // Date
                                var dateCommaSeparated = to.replace('Date(', '')
                                    .replace(')', ''); // results in yyyy,m,d
                                var parts = dateCommaSeparated.split(',');
                                to = new Date(parts[0], parts[1], parts[2]);
                            }
                            var val = new BOILib.Range(encStart, from, to, encClose);
                            tempVar = this.createContextVariable(pname, null,
                                vtype, BOILib.SelectionTypes.Range);
                            tempVar.ranges.push(val);
                            break;
                    }

                    varsSet[tempVar.name] = tempVar;
                }
            }

        } else if (vars) // vars must be a hashset
        {
            varsSet = vars;
            var varcount = 0;
            for (var i in vars) // i is the varname here
            {
                varcount++;
                if (this.context.variables[i]) // if already in context, set
                // its value
                    this.context.variables[i].value = vars[i];
                else {
                    var newvar = new BOILib.Variable();
                    newvar.name = i;
                    newvar.value = vars[i];

                    this.context.variables[i] = newvar;
                }
            }

            if (BOI.single_variable_screen) {
                // If the application has single variable screen
                if (varcount > 0) {
                    // All reports will have obsolete viewstate due
                    // to being affected by new variables values
                    for (var i in parent.context.reports) {
                        parent.context.reports[i].state = BOILib.ReportStates.RefreshNeeded;
                    }
                }
            }

            if (parent.debugMode)
                BOI.log += BOILib.Util.log('Parsed Variables ' + varcount);
        }

        // get report object from catalog
        if (this.context.reports[id]) // report exist in context
        {
            if (refresh)
                this.context.reports[id].state = BOILib.ReportStates.RefreshNeeded;
            else
                this.context.reports[id].state = BOILib.ReportStates.Current;

            if (parent.debugMode)
                BOI.log += BOILib.Util.log('Report Exists in Context '
                    + this.context.reports[id].id + ', '
                    + this.context.reports[id].tech_name);
            // register vars in report
            if (varsSet) // vars must be a hashset
            {
                for (var i in varsSet)
                    // i is the varname here
                    this.context.reports[id].variables[i] = this.context.variables[i];
            }

            if (parent.debugMode)
                BOI.log += BOILib.Util.log('Use Report Variables Only = '
                    + reportVarsOnly + ', Report URL is ' + url);

            // if the metadata is previously loaded, there is no need to refresh
            // again
            if (this.context.reports[id].metadata) {
                this.context.reports[id].state = BOILib.ReportStates.Executed;
            }

            if (this.context.reports[id].type == BOILib.ReportTypes.URL) {
                BOI.triggerReport(BOI.context.reports[id], target,
                    contextDocument, reportVarsOnly);
                if (successFunction) {
                    successFunction()
                }
                ;
                return url;
            } else if (this.context.reports[id].state == BOILib.ReportStates.RefreshNeeded) {
                BOI.loadReportMeta(BOI.context.reports[id], function (meta) {

                    BOI.triggerReport(BOI.context.reports[id], target,
                        contextDocument, reportVarsOnly);

                    if (successFunction)
                        successFunction();

                    return url;

                });
            } else {
                BOI.triggerReport(BOI.context.reports[id], target,
                    contextDocument, reportVarsOnly);
                if (successFunction)
                    successFunction();
            }

            return url;
        } else // report does not exist in context
        {
            if (parent.debugMode)
                BOI.log += BOILib.Util.log('Report Does Not Exist in Context ');
            // new report
            report = new BOILib.Report();
            report.id = id;
            report.tech_name = id;
            report.type = type;
            report.url = 'http://' + parent.urlForServer + '/'
                + parent.urlForOpenDocument + id; // TODO: must be
            // retrieved..

            if (refresh)
                report.state = BOILib.ReportStates.RefreshNeeded;
            else
                report.state = BOILib.ReportStates.Current;

            // register vars under the new report
            var vcount = 0;
            if (varsSet) // vars must be a hashset
            {
                for (var i in varsSet) // i is the varname here
                {
                    vcount++;
                    report.variables[i] = this.context.variables[i];
                }
            }
            if (parent.debugMode)
                BOI.log += BOILib.Util.log('Report Created in Context '
                    + report.id + ' with ' + vcount
                    + ' New Variables, URL: ' + report.url);
            // add report to context
            this.context.reports[id] = report;

            // get report variables and insert the vars into context
            this.loadReportMeta(parent.context.reports[id], function () {
                if (reportVarsOnly) { // return
                    // this.context.generateReportUri(report,
                    // true);
                    url = parent.context.generateReportUri(
                        parent.context.reports[id], true).post(target);
                    if (parent.debugMode)
                        BOI.log += BOILib.Util
                            .log('Generated POST Report URL: ' + url);
                    report.state = BOILib.ReportStates.Current;
                    return url;
                } else { // return this.context.generateReportUri(report);
                    url = parent.context.generateReportUri(
                        parent.context.reports[id]).post(target);
                    if (parent.debugMode)
                        BOI.log += BOILib.Util
                            .log('Generated POST Report URL: ' + url);
                    report.state = BOILib.ReportStates.Current;
                    return url;
                }
            });

        }

    },

    triggerReport:function (report, target, contextDocument, reportVarsOnly) {
        var url;
        switch (report.type) {
            case BOILib.ReportTypes.Flash:
            case BOILib.ReportTypes.Xcelsius:
            case BOILib.ReportTypes.XcelsiusLocal:
            case "FLASH":
            case "BO_DASHBOARD":
            case "BW_DASHBOARD":
                BOI.Flash.executeFlashReport(report, report.variables, target,
                    contextDocument);
                /*
                 * var container = $(contextDocument).find('[name="' + target +
                 * '"]').parent().get(0);
                 * if(container.getElementById(BOI.context.reports[id])) { //swf is
                 * already loaded var urls =
                 * BOI.context.reports[id].DATA_PROVIDER.split('|'); for(i=0;i<urls.length;i++) {
                 * //TODO: Revise and make sure variables is filled using queries
                 * from dataprovider list BOI.Flash.sendEIC(BOI.context.reports[id],
                 * "url" + (i+1), BOI.context.getBex3URL(urls[i],
                 * BOI.context.reports[id].variables), contextDocument); } } else {
                 * var swfEl = BOI.Flash.getSwf(BOI.context.reports[id]);
                 * $(contextDocument).find('[name="' + target +
                 * '"]').parent().append(swfEl); $(contextDocument).find('[name="' +
                 * target + '"]').remove(); }
                 */
                break;
            default:
                if (report.OPEN_STYLE)
                    if (report.OPEN_STYLE != '_SELF' && report.OPEN_STYLE != "")
                        target = report.OPEN_STYLE;
                url = BOI.context.generateReportUri(report, reportVarsOnly).post(
                    target);
                break;
        }

        report.state = BOILib.ReportStates.Current;// report viewstate is now
        // up to date
        return url;

    },
    //Jan 01-22-14 add args by abdulmajeed.
    executeReport:function (report, query, successFunction, args) {

        if (report != undefined && !report.metadata) {
            BOI.loadReportMeta(report, function (meta) {
                BOI.executeReport_internal(report, query, successFunction, args);
            });
        }
        else {
            BOI.executeReport_internal(report, query, successFunction, args);
        }
    },

    executeReport_internal:function (report, query, successFunction, args) {

        if (report) { // ignore query if report is set

            // Sefuvan edited to read first data_provider value from report instead of techname
            var data_provider="";
            if(report.data_provider != undefined){
                data_provider = report.data_provider.split("|")[0];
            }
            query = BOILib.BexSyntax.getBex3URL(data_provider,
                report.variables);
        }
        var url = window.location.href.substr(0, window.location.href
            .indexOf('/bsp/sap/') + 9)
            + "zbw_reporting/execute_report_oo.htm?query=" + query;

        //Jan 01-22-14 add args by abdulmajeed.
        if (typeof args !== "undefined") {
            for (var arg in args) {
                url += '&' + arg + '=' + args[arg];
            }
        }

        $.ajax({
            url:url,
            dataType:'xml',
            cache:false,
            success:function (data) {
                if (successFunction)
                    successFunction(data);
            }
        });
    },

    // TODO: Communication between two Xcelsius reports
    refreshReport:function (id, type, vars, reportVarsOnly, target, refresh) {
        if (this.context.reports[id]) // if exists
        {
            var report = this.context.reports[id];
            if (report.type == BOILib.ReportTypes.Xcelsius
                || report.type == BOILib.ReportTypes.Xcelsius
                || report.type == BOILib.ReportTypes.Flash) {
                // refresh Xcelsius using EIC
                for (var i in report.variables) // set each variable to its
                    // value in the swf object
                {
                    if (report.element) // element is a reference to the swf
                    // object
                        report.element.setDataSource(
                            report.variables[i].tech_name,
                            report.variables[i].value);
                }
            } else
                this
                    .openReport(id, type, vars, reportVarsOnly, target,
                        refresh);
        } else
            this.openReport(id, type, vars, reportVarsOnly, target, refresh);
    }

};
/* Add for drill function, which will show the drill frame and hide */
BOI.DrillSpec = {


    backButtonClicked:false,
    firstTime:true,
    drill_target:undefined,
    hideDrill:undefined,
    showDrill:undefined,
    goBack:undefined,
    backBtn:undefined,
    drillReportVisible:false,
    init:function (drill_target, backBtn) {
        BOI.DrillSpec.drill_target = drill_target;
        BOI.DrillSpec.backBtn = backBtn;
        (BOI.DrillSpec.drill_target).load(function () {
            if (BOI.DrillSpec.firstTime) {
                BOI.DrillSpec.firstTime = false;
                return;
            }
            if (!BOI.DrillSpec.backButtonClicked) {
                BOI.DrillSpec.showDrill();
                BOI.DrillSpec.drillReportVisible = true;
            }
            BOI.DrillSpec.backButtonClicked = false;
        });
        BOI.DrillSpec.goBack = function () {
            (BOI.DrillSpec.drill_target).attr('src', '');
            BOI.DrillSpec.hideDrill();
            BOI.DrillSpec.backButtonClicked = true;
            BOI.DrillSpec.drillReportVisible = false;
        };
        (BOI.DrillSpec.backBtn).live("click", BOI.DrillSpec.goBack);

    }

};

BOI.Designer = {
    app_id:undefined,
    Layout:{
        element:null,
        panels:{ // default set of panels
            TOP:{},
            LEFT:{},
            RIGHT:{},
            BOTTOM:{},
            CENTER:{}
        },
        assignComponent:function (panel_id, comp_id, order) {
            return BOI.Designer.Layout.panels[panel_id].assignComponent(
                comp_id, order);
        },
        unassignComponent:function (panel_id, comp_id) {
            BOI.Designer.Layout.panels[panel_id].unassignComponent(comp_id);
        }
    },
    Script:"", // custom URL to script to execute after initialization
    Components:{}, // hashset of available components (lookup)
    VariableViews:{},
    initialize:function (layout_element_id, app_id, callbackFn, loadComponents) { // prepare
        // the
        // designer
        // layout
        this.app_id = app_id;
        BOI.app_id = app_id;

        // set the layout element
        BOI.Designer.Layout.element = $('#' + layout_element_id).get(0);

        // initialize the layout panels
        BOI.Designer.Layout.panels['TOP'] = new BOILib.Panel(layout_element_id,
            'TOP');
        BOI.Designer.Layout.panels['LEFT'] = new BOILib.Panel(
            layout_element_id, 'LEFT');
        BOI.Designer.Layout.panels['RIGHT'] = new BOILib.Panel(
            layout_element_id, 'RIGHT');
        BOI.Designer.Layout.panels['BOTTOM'] = new BOILib.Panel(
            layout_element_id, 'BOTTOM');
        BOI.Designer.Layout.panels['CENTER'] = new BOILib.Panel(
            layout_element_id, 'CENTER');

        // load designer data
        BOIData.read
            .getDesigner(
            app_id,
            function (data) {

                $('#bi_debug').val(data);
                // traverse xml and populate

                BOI.Designer.Script = $(data).find(
                    'APP_INFO CUSTOM_SCRIPT').text();
                var panels = $(data)
                    .find('APP_LAYOUT PANELS PANEL');
                var available_variable_views = $(data).find(
                    'VARIABLE_VIEWS VIEW');
                var available_components = $(data).find(
                    'AVAILABLE_COMPONENTS COMPONENT');
                var ui_comp_lister = $('#bi_components ul');
                var other_params = $(data).find(
                    'APP_INFO OTHER_DETAILS').text();
                if (other_params != undefined) {
                    var app_param_ar = other_params.split("|");
                    var keyValue = null;
                    if (app_param_ar != undefined) {
                        for (var i in app_param_ar) {
                            keyValue = app_param_ar[i].split("=");
                            BOI.app_params[keyValue[0]] = keyValue[1];
                        }
                    }
                }
                BOI.home_report = $(data).find(
                    'APP_INFO HOME_REPORT').text();
                // 2-feb-2014 : Ansaj added for removing the home report from catalog
                BOI.remove_home = $(data).find('APP_INFO REMOVE_HOME').text();
                // 16-feb-2014 : Ansaj added for removing the home report from catalog
                BOI.add_theme = $(data).find('APP_INFO THEME').text();
                // build available variable views
                available_variable_views
                    .each(function () {
                        var view_xml = $(this);
                        var view_id = view_xml.find('VIEW_ID')
                            .first().text();

                        BOI.Designer.VariableViews[view_id] = new BOILib.Component(
                            view_id);

                        var view = BOI.Designer.VariableViews[view_id];

                        view.title = view_xml.find('VIEW_NAME')
                            .first().text();
                        view.description = view_xml.find(
                            'VIEW_NAME').first().text();
                        view.url = view_xml.find('URL').first()
                            .text();

                        // default properties
                        view.properties.variable = undefined;
                        view.properties.value = '';
                    });

                // build available components
                available_components
                    .each(function () {
                        var comp_xml = $(this);
                        var comp_id = comp_xml.find('COMP_ID')
                            .first().text();

                        BOI.Designer.Components[comp_id] = new BOILib.Component(
                            comp_id);

                        var comp = BOI.Designer.Components[comp_id];

                        comp.title = comp_xml.find('TITLE')
                            .first().text();
                        comp.description = comp_xml.find(
                            'DESCRIPTION').first().text();
                        comp.url = comp_xml.find('URL').first()
                            .text();

                        // create component element
                        // var element = $("<li id='" + comp_id
                        // + "'>" +
                        // BOILib.Util.ucwords(comp.title) +
                        // "<p>" +
                        // BOILib.Util.ucwords(comp.description)
                        // + "</p></li>").get(0);
                        // comp.element = $("<iframe src='" +
                        // comp.url + "'></iframe>").get(0);
                        // ui_comp_lister.append(comp.element);

                        // component properties
                        var comp_props = comp_xml
                            .find('PROPERTIES PROPERTY');
                        comp_props
                            .each(function () {
                                var prop_xml = $(this);
                                var prop_name = prop_xml
                                    .find('PROP')
                                    .first().text();

                                comp.properties[prop_name] = new BOILib.Property(
                                    comp.comp_id,
                                    prop_name);

                                var property = comp.properties[prop_name];

                                property.description = prop_xml
                                    .find('DESCRIPTION')
                                    .first().text();
                                property.value = prop_xml
                                    .find('VALUE')
                                    .first().text();
                                property.display = prop_xml
                                    .find('DISP_TYPE')
                                    .first().text();
                                // can be textbox, dropdown,
                                // checkbox, radio
                                property.mode = prop_xml
                                    .find('TYPE')
                                    .first().text(); // s=single,
                                // m=multiple
                                // values

                                var opts_str = prop_xml
                                    .find('POS_VALUES')
                                    .first().text(); // split
                                // by |
                                if (opts_str.indexOf('|') > -1) {
                                    var opts = opts_str
                                        .split('|');
                                    for (var op in opts)
                                        if (op)
                                            property.options
                                                .push(opts[op]);
                                }
                            });
                    });

                // build the objects
                panels
                    .each(function () {
                        var panel_xml = $(this);
                        var panel_id = panel_xml.find(
                            'PANEL_ID').first().text();

                        var panel = BOI.Designer.Layout.panels[panel_id]; // reference
                        // to
                        // current
                        // layout
                        // panel

                        panel.properties.width.value = panel_xml
                            .find('WIDTH').first().text();
                        panel.properties.height.value = panel_xml
                            .find('HEIGHT').first().text();
                        panel.properties.collapsible.value = panel_xml
                            .find('COLLAPSE').text();
                        panel.properties.resizable.value = panel_xml
                            .find('RESIZE').text();
                        panel.properties.disabled.value = panel_xml
                            .find('DISABLE').text();

                        // panel assigned components
                        if (loadComponents != false) {
                            var panel_comps = panel_xml
                                .find('ASSIGNED_COMPONENTS COMPONENT');
                            panel_comps
                                .each(function () {
                                    var comp_xml = $(this);
                                    var comp_id = comp_xml
                                        .find('COMP_ID')
                                        .first().text();
                                    var comp_order = comp_xml
                                        .find(
                                            'DISPLAY_ORDER')
                                        .first().text();

                                    var comp = panel
                                        .assignComponent(
                                            comp_id,
                                            comp_order);

                                    // components property
                                    // values
                                    var comp_props = comp_xml
                                        .find('PROPERTIES PROPERTY');
                                    comp_props
                                        .each(function () {
                                            var prop_xml = $(this);
                                            var prop_name = prop_xml
                                                .find(
                                                    'PROP')
                                                .first()
                                                .text();
                                            if (comp.properties[prop_name])
                                                comp.properties[prop_name].value = prop_xml
                                                    .find(
                                                        'VALUE')
                                                    .first()
                                                    .text();
                                        });
                                    comp.setProperties();
                                });
                        }
                    });

                /*
                 * if(BOI.Designer.Script != "") { var script =
                 * document.createElement("script"); script.type =
                 * "text/javascript"; script.src =
                 * BOI.Designer.Script; // use this for linked
                 * script script.text = ""; // use this for inline
                 * script //document.body.appendChild(script);
                 * $("head").append(script); }
                 */

                callbackFn();
            });
    },
    saveAll:function () {
        // save all 4 panels ZCL_MYBW_COMP_PANEL | UPDATE
        // delete all assigned components in current app ZCL_MYBW_COMP_LOC |
        // DELETE | using parameter APP_ID
        // save panel assigned components ZCL_MYBW_COMP_LOC | UPDATE
        // save assigned component properties ZCL_MYBW_COMP_DEFINITION | UPDATE

        var panel_records = [], comp_records = [], prop_records = [];
        for (var p in BOI.Designer.Layout.panels) {
            var panel = BOI.Designer.Layout.panels[p];
            panel_records.push(panel.getAssignmentRecord());

            for (var c in panel.components) {
                var comp = panel.components[c];
                comp_records.push(comp.getAssignmentRecord());

                for (var i in comp.properties) {
                    var prop = comp.properties[i];
                    prop_records.push(prop.getAssignmentRecord());
                }
            }
        }

        var panel_req = BOIData.request.prepare("ZCL_MYBW_COMP_PANEL",
            "UPDATE", panel_records);
        var comp_req_del = BOIData.request.prepare("ZCL_MYBW_COMP_LOC",
            "DELETE",

            [ BOIData.data.createRecord({
                APP_ID:[ BOI.app_id ]
            }) ]);
        var comp_req = BOIData.request.prepare("ZCL_MYBW_COMP_LOC", "UPDATE",
            comp_records);
        var prop_req = BOIData.request.prepare("ZCL_MYBW_COMP_DEFINITION",
            "UPDATE", prop_records);

        $('#bi_debug').val(panel_req + comp_req_del + comp_req + prop_req);

        // return;

        // perform the requests
        BOIData.request
            .perform(
            panel_req,
            "text",
            "POST",
            function (data) {
                // panels have been saved
                BOIData.request
                    .perform(
                    comp_req_del,
                    "text",
                    "POST",
                    function (data) {
                        // component assignments cleared
                        BOIData.request
                            .perform(
                            comp_req,
                            "text",
                            "POST",
                            function (data) {
                                // component
                                // assignments
                                // created
                                BOIData.request
                                    .perform(
                                    prop_req,
                                    "text",
                                    "POST",
                                    function (data) {
                                        // component
                                        // assignments
                                        // properties
                                        // values
                                        // set
                                        // created
                                        alert('All Data Saved Successfully');

                                    });

                            });

                    });
            });

    },
    addComponent:function (comp_id, iframe, panel_id, properties) {
        var comp = BOI.Designer.Layout.panels[panel_id].assignComponent(
            comp_id, 0);
        for (var i in properties) {
            if (comp.properties)
                if (comp.properties[i])
                    comp.properties[i].value = properties[i];
        }
    },
    setPanel:function (panel_id, width, height, collapse, resize, disable) {
        BOI.Designer.Layout.panels[panel_id].properties.width = width;
        BOI.Designer.Layout.panels[panel_id].properties.height = height;
        BOI.Designer.Layout.panels[panel_id].properties.collapsible = collapse;
        BOI.Designer.Layout.panels[panel_id].properties.resizable = resize;
        BOI.Designer.Layout.panels[panel_id].properties.disabled = disable;
    },

    // Show/Hide function Components added by Faisal
    showHideComponents:function (rep_id) {
        var report = BOI.context.reports[rep_id];
        if (report) {
            if (BOI.Designer) {
                if (BOI.Designer.layout) {
                    if (BOI.Designer.layout.panels) {
                        for (var p in BOI.Designer.Layout.panels) {
                            var panel = BOI.Designer.Layout.panels[p];
                            for (var c in panel.components) {
                                var comp = panel.components[c];
                                if (comp.iframe) {
                                    if (comp.iframe.properties.varname) {
                                        var vname = comp.iframe.properties.varname;
                                        if (report.variables[vname]) {
                                            $(comp.element).show();
                                        }
                                        else {
                                            $(comp.element).hide();
                                        }
                                    }

                                }
                            }
                        }
                    }
                }
            }
        }
    }

};

BOI.Events = {
    _events:{},
    addListener:function (eventName, callback) {
        var events = this._events, callbacks = events[eventName] = events[eventName]
            || [];
        callbacks.push(callback);
    },
    raiseEvent:function (eventName, args) { // notifies all listeners
        var callbacks = this._events[eventName];
        if (callbacks)
            for (var i = 0, l = callbacks.length; i < l; i++) {
                callbacks[i](args);
            }
    },
    contextchange:"contextchange",
    appchange:"appchange",
    repchange:"repchange",
    repvarchange:"repvarchange",
    repopen:"repopen",
    varchange:"varchange",
    varrefresh:"varrefresh",
    varreset:"varreset",
    propchange:"propchange",
    favchange:"favchange",
    favopen:"favopen",
    groupopen:"groupopen",
    maximize:"maximize",
    minimize:"minimize",
    rangechange:"rangechange", // xcelsuis
    app_loaded:"app_loaded",
    period_change:"period_change", // Added for handling MIS Catalog
    loaddata:"loaddata",
    icon:"icon",
    show_comment:"false", // for comment button
    resize:"resize"
};

BOI.Flash = {

    executeFlashReport:function (report, variables, target, contextDocument) {
        if (report) {
            // var container = $(contextDocument).find('[name="' + target +
            // '"]').parent().get(0);
            if ((contextDocument.getElementById(report.id)) && ((report.DATA_PROVIDER != undefined) && (report.DATA_PROVIDER != "undefined") && report.DATA_PROVIDER != "")) {
                // swf is already loaded
                if (report.DATA_PROVIDER != undefined) {
                    var urls = report.DATA_PROVIDER.split('|');
                    for (i = 0; i < urls.length; i++) {
                        var variables;
                        var baseurl = undefined;
                        if (BOI.app_params != undefined) {
                            if (BOI.app_params["flash_data_model"]) {
                                baseurl = BOI.app_params["flash_data_model"];
                            }
                        }
                        variables = BOI.context.getReportVariables(report.id,
                            true);
                        BOI.Flash.sendEIC(report, "url" + (i + 1),
                            BOILib.BexSyntax.getBex3URL_XML(urls[i],
                                variables, baseurl), contextDocument);
                    }
                }
            } else {
                var swf_element = BOI.Flash.getSwf(report);
                $(contextDocument).find('[name="' + target + '"]').parent()
                    .append(swf_element);
                $(contextDocument).find('[name="' + target + '"]').remove();
            }
        }
    },

    removeFlashReport:function (report, contextDocument) {
        var movie = BOI.Flash.getMovie(report.id, contextDocument);

        if (movie != null) {
            var parentElelent = $(movie).parent().get(0);
            if (parentElelent) {
                parentElelent.removeChild(movie);
                parentElelent.innerHTML = '';
            }

        }

    },

    removeReportGroup:function (report, contextDocument) {
        for (var i in report.reports) {
            var rep = report.reports[i];
            if (rep.type == "FLASH" || rep.type == "BO_DASHBOARD"
                || rep.type == "BW_DASHBOARD") {
                BOI.Flash.removeFlashReport(rep, contextDocument);
            }

        }
    },
    getURLForFlashVar:function getURLForFlashVar(report) {

        var totalFlashVars = "";
        if (report.DATA_PROVIDER != undefined) {
            var urls = report.DATA_PROVIDER.split('|');
            for (i = 0; i < urls.length; i++) {
                var variables;
                var baseurl = undefined;
                if (BOI.app_params != undefined) {
                    if (BOI.app_params["flash_data_model"]) {
                        baseurl = BOI.app_params["flash_data_model"];
                    }
                }
                variables = BOI.context.getReportVariables(report.id, true);
                var url = BOILib.BexSyntax.getBex3URL_XML(urls[i], variables,
                    baseurl);
                url = encodeURIComponent(url);
                totalFlashVars = totalFlashVars + "&url" + (i + 1) + "=" + url;
            }
        }
        return totalFlashVars;
    },
    getSwf:function getSwf(report) {
        // var variables ;
        // variables = BOI.context.getReportVariables(report.id, true);

        // var flashvars = BOILib.BexSyntax.getBEX3Variables(variables);
        // var flashvars = BOI.context.generateXcelsiusURL(report.id,
        // report.type, true);

        var flashvars = this.getURLForFlashVar(report);

        var swfTemplate = '<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'
            + 'codebase="http://fpdownload.adobe.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" '
            + 'WIDTH="100%" HEIGHT="100%" id="'
            + report.id
            + '">'
            + '<PARAM NAME=FlashVars VALUE="'
            + flashvars
            + '">'
            + '<PARAM NAME="movie" VALUE="'
            + report.url
            + '"> '
            + '<param name="wmode" value="opaque" />'
            + '<PARAM NAME="quality" VALUE="high">'
            + '<PARAM NAME="bgcolor" VALUE="#FFFFFF">'
            + '<PARAM NAME="play" VALUE="true">'
            + '<PARAM NAME="loop" VALUE="true">'
            + '<PARAM NAME=bgcolor VALUE="#FFFFFF">'
            + '<PARAM NAME="SCALE" VALUE="exactfit">'
            + '<EMBED src="'
            + report.url
            + '" quality=high bgcolor=#FFFFFF WIDTH="100%" HEIGHT="100%" '
            + 'NAME="'
            + report.id
            + '" ALIGN="" TYPE="application/x-shockwave-flash" wmode="opaque" '
            + 'play="true" loop="true" SCALE="exactfit" '
            + 'FlashVars="'
            + flashvars
            + '" '
            + 'PLUGINSPAGE="http://www.adobe.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">'
            + '</EMBED>' + '</OBJECT>';
        return swfTemplate;
    },
    getMovie:function getMovie(movieName, contextDocument) {
        contextDocument = typeof contextDocument == 'undefined' ? document
            : contextDocument;

        var movie = undefined;
        if (navigator.appName.indexOf("Microsoft") != -1) {
            movie = contextDocument.getElementById(movieName);
        } else {
            movie = contextDocument[movieName];
        }
        return movie;
    },
    sendEIC:function sendEIC(report, varname, value, contextDocument) {
        try {
            if (report) {
                var movie = BOI.Flash.getMovie(report.id, contextDocument);
                if (movie) {
                    BOI.Flash.getMovie(report.id, contextDocument)
                        .setDataSource(varname, value);
                }
            }
        } catch (e) {
            BOILib.Util.log("Error in sending EIC for report : " + report.name
                + "::" + e, false);

        }

    },
    initMovieBindings:function (report, contextDocument) {

        // Available Xcelsius External Interface calls:
        // movie.describeDataSources():XML
        // movie.getDataSource(rangeName:String):Object
        // movie.setDataSource(rangeName:String, newValue:Object):void
        // movie.addDataSourceChangeEventListener(rangeName:String,
        // handlerFunctionName:String, sendCurrentValue:Boolean):void
        // movie.removeDataSourceChangeEventListener(rangeName:String,
        // handlerFunctionName:String):void

        // Call the "rangeChangeHandler" callback handler when the range values
        // change.
        var sendCurrentValue = true; // false (do not pass current value),
        // true (pass current value via
        // callback).

        // create EIC listeners for dataproviders (urls)
        /**/
        var providers = report.DATA_PROVIDER.split('|');
        var count = providers.length;

        for (i = 0; i < count; i++)
            BOI.Flash.getMovie(report.id, contextDocument)
                .addDataSourceChangeEventListener("url" + (i + 1),
                    "rangeChangeHandler", sendCurrentValue);

        // create EIC listeners for variables
        for (var i in report.variables)
            BOI.Flash.getMovie(report.id, contextDocument)
                .addDataSourceChangeEventListener(report.variables[i].name,
                    "rangeChangeHandler", sendCurrentValue);

    },
    setSWFIsReady:function setSWFIsReady(movieName, contextDocument) {
        BOI.Flash.initMovieBindings(BOI.context.reports[movieName],
            contextDocument);
        BOI.Events.raiseEvent(BOI.Events.loaddata,
            [ movieName, contextDocument ]);
    },
    rangeChangeHandler:function rangeChangeHandler(movieName, rangeName, contextDocument) {
        // Get the new range value.
        var newValue = BOI.Flash.getMovie(movieName, contextDocument)
            .getDataSource(rangeName);
        BOI.Events.raiseEvent(BOI.Events.rangechange, [ rangeName, newValue,
            movieName ]);
        // alert(newValue);
    }
};

/*
 * function setSWFIsReady(movieName) { alert('BOI caught');
 * BOI.Flash.setSWFIsReady(movieName); }
 */
/*
 * function rangeChangeHandler(movieName, rangeName) { //alert('change caught');
 * BOI.Flash.rangeChangeHandler(movieName, rangeName); }
 */
/** BOI initialization * */
$(function () {
    /* Required Dynamic iFrame */
    $(
        '<iframe id="boi_open_report" name="boi_open_report" style="display:none;">')
        .appendTo('body');
    BOI.context.parent = BOI;

    var url_bw_root = BOILib.Util.getBaseUrlBWAbap();

    // initial values in case unable to communicate
    BOI.urlForServer = "dj1.aramco.com.sa";
    BOI.urlForOpenDocument = "BOE/OpenDocument/opendoc/openDocument.jsp?sIDType=CUID&iDocID=";
    BOI.urlForVariableF4Search = url_bw_root + "zbw_reporting/var_search.htm?var_name={varname}&info_object={iobj}&infocube=ZMDOCOVER&read_mode=M&search_term=";

    // Report Catalog - XML
    BOI.urlForReportCatalogXML = url_bw_root + "zbw_reporting/report_hier.do?view_name=dbd_rep_tree%2exml&template_id=";
    // Report Catalog - JSON
    BOI.urlForReportCatalogJSON = url_bw_root + "zbw_reporting/report_hier.do?view_name=dbd_rep_tree.JSON&template_id=";
    // Report variables information
    BOI.urlForReportMeta = url_bw_root + "zbw_reporting/variable_screen_ext.xml?rep_id=";
    // Variable F4 Values
    BOI.urlForVariableF4Paging = url_bw_root + "ZBW_REPORTING/variable_values_paging.xml?read_mode=C&page_flag=X&var_name=";
    BOI.urlForVariableF4 = url_bw_root + "ZBW_REPORTING/variable_values.xml?read_mode=C&var_name=";
    BOI.urlForVariableF4Query = url_bw_root + "zbw_reporting/execute_report_oo.htm?paging=X&query=";// sample
    // query:
    // YAC_03_HRSD_X_HRROLE_DEP
    // append
    // &page_no=1&num_records=10&paging=X&variables=<BEX3_SYNTAX_FOR_VARS>

    // bex7
    BOI.urlForBex7 = "http://dvb.aramco.com.sa:52000/irj/servlet/prt/portal/prtroot/pcd!3aportal_content!2fcom.sap.pct!2fplatform_add_ons!2fcom.sap.ip.bi!2fiViews!2fcom.sap.ip.bi.bex?query=";
    // bex3
    BOI.urlForBex3 = "http://dvb.aramco.com.sa:1080/sap/bw/BEx?query=";

    // wad3
    BOI.urlForWAD3 = "http://dvb.aramco.com.sa:1080/sap/bw/BEx?template_id=";
    // wad7
    BOI.urlForWAD7 = "https://khesab.aramco.com.sa:52001/irj/servlet/prt/portal/prtroot/pcd!3aportal_content!2fcom.sap.pct!2fplatform_add_ons!2fcom.sap.ip.bi!2fiViews!2fcom.sap.ip.bi.bex?TEMPLATE=";

    // var boi_urlForInit = "api/data/get_parameter_xml.xml"; //COMMENT THIS
    // WHEN GOING TO ONLINE MODE

    BOIData.lookup.getConfig('ALL', function (data) {
        BOI.log += BOILib.Util.log('BOI Initializing');

        var config = {};

        $(data).find('ITEM').each(function () {
            config[$(this).find('NAME').text()] = $(this).find('VALUE').text();
        });

        BOI.urlForServer = config['BO_SERVER'];// "http://[[[[[[[[dj1.aramco.com.sa]]]]]]]]/",

        BOI.protocolForBOServer = config['BO_PROTOCOL'];

        BOI.kpiURL = config['KPI_URL'];

        BOI.urlForBex7 = config['PRT_PROTCL'] + "://" + config['PRT_SERVER']
            + "/" + config['BI_LAUNCHER'] + "?query=";

        BOI.urlForBex3 = config['PRT_PROTCL'] + "://" + config['BW_SERVER']
            + "/" + "sap/bw/BEx?&query=";

        BOI.urlForWAD3 = config['PRT_PROTCL'] + "://" + config['BW_SERVER']
            + "/" + "sap/bw/BEx?variable_screen=&template_id=";
        BOI.urlForWAD7 = config['PRT_PROTCL'] + "://" + config['PRT_SERVER']
            + "/" + "/irj/servlet/prt/portal/prtroot/pcd!3aportal_content!2fcom.sap.pct!2fplatform_add_ons!2fcom.sap.ip.bi!2fiViews!2fcom.sap.ip.bi.bex?TEMPLATE=";

        // COMMENT THIS WHEN GOING TO ONLINE MODE
        // AS THESE ARE USED FOR OFFLINE TESTING ONLY
        /*
         * BOI.urlForReportCatalogXML = "api/data/report_hier.xml?id=";
         * BOI.urlForReportCatalogJSON = "api/data/report_hier.json?id=";
         * BOI.urlForReportMeta = "api/data/variable_screen_ext.xml?id=";
         * BOI.urlForVariableF4Paging = "api/data/variable_values.xml?id=";
         *
         * BOI.log+=BOILib.Util.log('BOI Initialized'); return;
         */
        // --------------------------------------------------
        // F4 Values to provide the name value pairs for the variable values
        // cycle=1 means the current page to begin with (defaulted here to first
        // page)
        // no_record means total number of records to show in the page
        // (defaulted here to 100)
        BOI.log += BOILib.Util.log('BOI Initialized');
    });

});




BOI.Portal = {
    app_catalog: [],

    getAppCatalogXML: function (successfn) {
        BOIData.list.getApps( function(data){

            /**
             * TODO:: Write method to fill the app catalog 'app_catalog'
             */

            if(successfn){
                successfn();
            }
        });

    },
    updateUserPreferences: function (type,pref, successfn) {

        var req = BOIData.request.prepare("ZCL_MYBW_PREFERENCES",
            BOIData.actions.update, [ BOIData.data.createRecord({
                "PREF_TYPE":[ type ],
                "PREFERENCE":[ pref ]
            }) ]);
        BOIData.request.perform(req, "text", "POST",  function(data){

            /**
             * TODO:: do the common functons after updating user preferences
             */

            if(successfn){
                successfn();    
            }
        });
    },
    readUserPreferences: function (type, successfn) {
        // need to write a new method
        BOIData.list.readUserPreferences(  function(data){

            /**
             * TODO:: do the common functons after reading user preferences
             */

            if(successfn){
                successfn();
            }
        });
    },
    searchBI: function (type, successfn) {
        // need to write a new method
        BOIData.list.searchBI(undefined, function(data){

            /**
             * TODO:: do the common functons after searching
             */

            if(successfn){
                successfn();
            }
        });
    }

};

/*
 * Merging the BOILib, Utils etc under the BOI. Otherwise each page
 * need to have a statement to assign the individual component.
 *
 */

BOI.theme = theme;
BOI.BOILib = BOILib;
BOI.BOIData = BOIData;
BOI.boi_ui = boi_ui;
BOI.currentDlg = currentDlg;


